TableHeaderScope.Column and HTML standards compliance

by chris.fulstow 6/28/2008 4:18:00 PM

Neil spotted this quirky behaviour in the TableHeaderCell control.  Suppose you've got a Table web control that renders a <table> tag with a <th scope="col">, using code something like this:

Table table = new Table()
{
    Rows =
    {
        new TableRow()
        {
            Cells =
            {
                new TableHeaderCell() { Scope = TableHeaderScope.Column, Text = "MyColumn" }
            }
        }
    }
};

Then the rendered HTML won't be W3C compliant because a scope value of "column" isn't valid:

<table border="0">
    <tr>
        <th scope="column"></th>
    </tr>
</table>

According to the W3C HTML and XHTML specs, the acceptable values for scope are [row|col|rowgroup|colgroup].  This is confirmed by the W3C Markup Validation Service, which reports the error:

XHTML validation error

Stepping into the source code for the TableHeaderCell control with Reflector or the .NET Reference Source, you can see the root of the problem:

protected override void AddAttributesToRender(HtmlTextWriter writer) {
    TableHeaderScope scope = Scope; 
    if (scope != TableHeaderScope.NotSet) {
        writer.AddAttribute(HtmlTextWriterAttribute.Scope, scope.ToString().ToLowerInvariant()); 
    }
}

When the control sets the scope attribute's value, it uses a lowercase string representation of the TableHeaderScope.Column enumeration, i.e. "column".  An enum value of TableHeaderScope.Col would've been ok, but TableHeaderScope.Column is invalid.

Workarounds

Neil has a good workaround by adding the scope attribute manually instead of using the TableHeaderCell.Scope property:

TableHeaderCell th = new TableHeaderCell();
th.Attributes["scope"] = "col";

I thought I'd have a go at extending this fix into a simple control adatper that makes sure TableHeaderCell always renders itself correctly.  It works by checking whether the Scope property is set to TableHeaderScope.Column, and if so manually adds the attribute scope="col" instead.  Here's the code:

public class TableHeaderCellAdapter : WebControlAdapter
{
    protected override void RenderBeginTag(HtmlTextWriter writer)
    {
        TableHeaderCell th = (TableHeaderCell) this.Control;
 
        if (th.Scope == TableHeaderScope.Column)
        {
            th.Scope = TableHeaderScope.NotSet;
            th.Attributes["scope"] = "col";
        }
 
        base.RenderBeginTag(writer);
    }
}

To associate the control adapter class with the TableHeaderCell control, add a browser definition file to the App_Browsers folder:

<!-- file: ~/App_Browsers/ControlAdapters.browser -->
<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter
        controlType="System.Web.UI.WebControls.TableHeaderCell"
        adapterType="TableHeaderCellAdapter"
      />
    </controlAdapters>
  </browser>
</browsers>

Tags: ,

Calais.NET - generating metadata using the Calais web service

by chris.fulstow 3/11/2008 2:47:00 PM

Calais.NET is a .NET 3.5 project that provides a friendly API to the Calais web service.

What is Calais?

Here's the official description of the service from the opencalais.com website:

The Calais web service automatically attaches rich semantic metadata to the content you submit – in well under a second. Using natural language processing, machine learning and other methods, Calais categorizes and links your document with entities (people, places, organizations, etc.), facts (person ‘x’ works for company ‘y’), and events (person ‘z’ was appointed chairman of company ‘y’ on date ‘x’).

So, in short, Calais extracts metadata from content you supply.  It takes input as HTML, XML or plain text, then tries to identify various types of metadata, such as companies, people, countries and quotations.  For a full list of supported metadata types, see Calais Semantic Metadata.

A good demo of the the service is the Calais Document Viewer Java application from the OpenCalais website.  Simply paste in some content, click 'Submit', and your original content will be returned with highlighted metadata.

The goal of Calais.NET is to provide the kind of functionality to .NET applications.

How to use Calais in your .NET project

The Calais.NET API wrapper makes Calais very simple to use from .NET.  It exposes a straightforward .NET interface that abstracts away web service details like complex XML input parameters and verbose RDF output data by processing the data with LINQ to XML.

Calais.NET code example

string content = (new WebClient()).DownloadString("http://news.bbc.co.uk/");
 
CalaisDotNet calais = new CalaisDotNet(ApiKey, CalaisContentType.Html, content);
calais.Call();
 
IEnumerable<string> entities = calais.ExtractMetadata(CalaisMetadata.Country);
foreach (string entity in entities)
{
    Console.WriteLine(entity);
}

Example output

Venezuela
Malta
United States
Canada
Sudan
Tibet
Spain
Serbia
China
Mozambique
United Kingdom
Sri Lanka 

Download

Download Calais.NET from Codeplex and give it a try.  C# .NET 3.5 source code included.

Configuring IIS 7 for ASP.NET on Vista

by chris.fulstow 3/6/2008 9:20:00 PM

As part of Microsoft's ongoing Trustworthy Computing initiative, Vista takes the secure by default principle more seriously than previous versions of Windows.  Consequently, many features aren't installed by default, one of which is IIS 7.  So, to install IIS go to:

Control Panel - Programs - Turn Windows features on or off

Then find the Intenet Information Services section and add everything you need, including ASP.NET.

image

Tags: ,

Tips

Installing ASP.NET Membership, Roles and Profiles support in SQL Server

by chris.fulstow 2/22/2008 7:07:00 PM

Here are are a few quick tips if you're using the ASP.NET Application Services with SQL Server, like Membership, Roles, Profiles, Personalization or Web Events.

These built-in "building-block" services have SQL provider implementations in .NET that let you use a SQL Server 2000 or 2005 database as their data store.  These are the framework classes that implement the SQL Server providers:

ASP.NET SQL Server Registration Tool

Adding support for these providers to your database is easy, just run the ASP.NET SQL Server Registration tool from the command-line (aspnet_regsql.exe) to launch the ASP.NET SQL Server Setup Wizard.  This will guide you through the process with a simple GUI:

> cd C:\Windows\Microsoft.NET\Framework\v2.0.50727
> aspnet_regsql.exe

By default, the wizard installs all five services: Membership, Roles, Profiles, Personalization and Web Events.  However, if you need support for only some, say just Membership and Roles, then aspnet_regsql can be run from the command-line with specific options, for example:

> aspnet_regsql -S MySqlServer -E -A mr -d MyAspDatabase

This installs the Membership and Roles services (-A mr) on server MySqlServer in database MyAspDatabase using current Windows credentials for authentication.  To see a full list of command-line options and switches, run the registration tool with the help flag:

> aspnet_regsql.exe /?

There's also an option to generate just SQL scripts without executing them, and another to remove services from the database that aren't used or needed anymore. (You can also manage SQL cache dependencies and session state using this tool.)

For more info about ASP.NET SQL providers:

Powered by BlogEngine.NET 1.3.0.0
Theme by Mads Kristensen

About the author

Name of author Chris Fulstow
ASP.NET Contractor, Sydney

E-mail me Send mail

Calendar

<<  October 2008  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar

Pages

    Recent comments

    Categories


    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2008

    Sign in