March, 2010 Archives
Mar
Validate XHtml 1.0 Strict as part of your build process
by Mikael Lundin in Programming
If one of the requirements for the website you’re building is that it should validate XHtml 1.0 Strict, then you can’t mearly use the W3C Validator, but have to make it a part of your build process. That you do, by turning the validation into a test.
First, you need to get those URLs. I get mine from a sitemap.xml.
private IEnumerable<string> GetTargetUrls(string googleSiteMapUrl)
{
XNamespace xmlns = "http://www.sitemaps.org/schemas/sitemap/0.9";
var document = XDocument.Load(googleSiteMapUrl);
return from loc in document.Descendants(xmlns + "loc")
select loc.Value;
}
Next, I get the HTML content for those URLs.
private Stream GetHtmlContent(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = "W3C_Validator/1.0 libwww-perl/0.40";
return request.GetResponse().GetResponseStream();
}
And now we’re ready to do the validation. But first, you download the XHtml 1.0 Strict Schema and include it in your project as an Embedded Resource. That way you don’t have to worry about where the file ends up after compilation.
You will easily get a stream to this file with the following method. This takes for granted that it is placed in the same namespace/path as the calling instance method.
private Stream GetEmbeddedResource(string relativePath)
{
string path = string.Format("{0}.{1}", GetType().Namespace, relativePath);
return Assembly.GetCallingAssembly().GetManifestResourceStream(path);
}
Now we’re ready to write the test. For each URL in the sitemap, it will load its HTML into an XmlDocument and validate it with the schema. If the validation fails, it will throw an AssertionException that will be caught and registered in the errorMessage result string. This way, we will continue and test all URLs even when one fails its validation.
[Test]
public void ShouldValidate()
{
/* Setup */
var urls = GetTargetUrls(GoogleSiteMapUrl);
bool isValid = true;
var errorMessage = new StringBuilder();
/* Test */
foreach (var url in urls)
{
try
{
using (var xsd = GetEmbeddedResource(ValidationSchema))
using (var html = GetHtmlContent(url))
{
// If the html is XHtml Strict, this should be possible
var result = new XmlDocument();
result.Load(html);
using (TextReader schemaReader = new StreamReader(xsd))
{
var callback = new ValidationEventHandler(ValidationCallBack);
var schema = XmlSchema.Read(schemaReader, callback);
result.Schemas.Add(schema);
result.Validate(callback);
}
}
}
catch (Exception e)
{
isValid = false;
errorMessage.AppendFormat("{0}: {1}\n", url, e.Message);
}
}
/* Assert */
Assert.IsTrue(isValid, errorMessage.ToString());
}
private static void ValidationCallBack(object sender, ValidationEventArgs e)
{
Assert.Fail(e.Severity + ": " + e.Message);
}
You can download the whole code example from here. Happy testing!
Mar
Hand rolling your datalayer
by Mikael Lundin in Programming
There are higher and higher demands on you as a developer to learn more and more frameworks that I sometimes get lost in the djungle out there. If you ask me to store some data into a database my mind will automatically go into an NHibernate, Entity Framework, Linq 2 SQL, Castle Active Record mantra and start discussing with itself what is the perfect framework for this specific problem.
When you have four entities you don’t really need an ORM to handle persistance. In fact, using an ORM in that case is same as “stealing from your clients“. (I’m aware that the link goes to a post that states the opposite of my argument)
I suggest we take a moment here to reflect on how you hand roll a data layer that will suit for up to four entities.
First we need some sort of provider that may deliver us data connections and commands. Some sort of object that will get the plumbing out of the way.
/// <summary>
/// Provider class for the database connection and command
/// </summary>
public class DataProvider : IDataProvider
{
private readonly ConnectionStringSettings settings;
/// <summary>
/// Create new instance of DataProvider
/// </summary>
/// <param name="connectionStringName">Name of the active connectionString in the App.Config/Web.Config</param>
public DataProvider(string connectionStringName)
{
settings = ConfigurationManager.ConnectionStrings[connectionStringName];
if (settings == null)
{
throw new ConfigurationErrorsException("Expected a connectionString with the name " + connectionStringName);
}
DbProviderFactory = DbProviderFactories.GetFactory(settings.ProviderName);
}
/// <summary>
/// Gets the DbProviderFactory
/// </summary>
public DbProviderFactory DbProviderFactory { get; private set; }
/// <summary>
/// Opens a new connection to the database. Make sure you close it before you're done.
/// </summary>
/// <returns>An open DbConnection</returns>
public DbConnection OpenConnection()
{
var connection = DbProviderFactory.CreateConnection();
connection.ConnectionString = settings.ConnectionString;
connection.Open();
return connection;
}
/// <summary>
/// Creates a new DbCommand
/// </summary>
/// <param name="connection">The connection we utilize for this command</param>
/// <param name="query">The SQL query to run</param>
/// <returns>The DbCommand</returns>
public DbCommand CreateCommand(DbConnection connection, string query)
{
var command = DbProviderFactory.CreateCommand();
command.Connection = connection;
command.CommandText = query;
return command;
}
/// <summary>
/// Creates a DbParameter for parameterized database calls
/// </summary>
/// <param name="name">Name of the parameter</param>
/// <param name="type">Type of the parameter</param>
/// <param name="value">Value of the parameter</param>
/// <returns>A DbParameter</returns>
public DbParameter CreateParameter(string name, DbType type, object value)
{
var parameter = DbProviderFactory.CreateParameter();
parameter.ParameterName = name;
parameter.DbType = type;
parameter.Value = value;
return parameter;
}
}
And this would be an example of how you can use that provider to talk to the database.
public class BookRepository
{
private const string GetByIdQuery = "SELECT title, author FROM books WHERE id=@id";
private readonly IDataProvider provider;
public BookRepository(IDataProvider provider)
{
this.provider = provider;
}
public Book GetById(int id)
{
using (var connection = provider.OpenConnection())
using (var command = provider.CreateCommand(connection, GetByIdQuery))
{
var idParameter = provider.CreateParameter("id", DbType.Int32, id);
command.Parameters.Add(idParameter);
var reader = command.ExecuteReader();
if (!reader.Read())
{
throw new DataException("Expected Book entity with id " + id + " in the database");
}
var result = new Book
{
Id = id,
Title = reader["title"] as string,
Author = reader["author"] as string
};
return result;
}
}
}
From your presenter or controller (or whatever) you may now use your data layer like this.
// Could use a DI framework here, but what the heck!
var repository = new BookRepository(new DataProvider("MyDatabaseConnection"));
var book = repository.GetById(1);
There’s nothing wrong with going back to the basics, sometimes.
