jQuery: Write less, do more

jQuery: Write less, do more

jQuery’s popularity has really exploded over last few years. What really stands out about jQuery is its clear and consise JavaScript library. Other things I’ve come to appreciate over time is its deep functionality and completely non-intrusive configuration. Recently, to improve the responsiveness of my user interfaces, I decided to use jQuery’s Ajax to call SOAP-XML web services directly. I struggled to find good information on how this can be done. There are a lot of good examples on the web that demonstrate how to use JSON web services from jQuery Ajax, but almost none for SOAP-XML web services.

.NET Web Service Operation Definition

.NET Web Service Operation Definition

Before you can call the web service from client script you need to obtain the web service operation’s WSDL. If you’re using a .NET web service, you can just point your browser to the web service’s URL, and click on the operation’s name.

The example web service operation I’m using, SaveProduct, has the following schema:

POST /ProductService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://sh.inobido.com/SaveProduct"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SaveProduct xmlns="http://sh.inobido.com/">
<productID>int</productID>
<productName>string</productName>
<manufactureDate>dateTime</manufactureDate>
</SaveProduct>
</soap:Body>
</soap:Envelope>

The method that will contact this operation looks like this:

var productServiceUrl = 'http://localhost:57299/ProductService.asmx?op=SaveProduct'; // Preferably write this out from server side

function beginSaveProduct(productID, productName, manufactureDate)
{
var soapMessage =
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> \
<soap:Body> \
<SaveProduct xmlns="http://sh.inobido.com/"> \
<productID>' + productID + '</productID> \
<productName>' + productName + '</productName> \
<manufactureDate>' + manufactureDate + '</manufactureDate> \
</SaveProduct> \
</soap:Body> \
</soap:Envelope>';

$.ajax({
url: productServiceUrl,
type: "POST",
dataType: "xml",
data: soapMessage,
complete: endSaveProduct,
contentType: "text/xml; charset=\"utf-8\""
});

return false;
}

function endSaveProduct(xmlHttpRequest, status)
{
 $(xmlHttpRequest.responseXML)
    .find('SaveProductResult')
    .each(function()
 {
   var name = $(this).find('Name').text();
 }
}

In order to call the web service, we need to supply an XML message that match the operation definition specified by the web service’s WSDL. With the operation’s schema already in hand, all that is required is to exchange the type names for the operation’s paramaters, with their actual values. The variable soapMessage contains the complete XML message that we’re going to send to the web service.

To make an Ajax request with jQuery you use the ajax method found on the jQuery object. The $/dollar sign is an alias for jQuery, the actual name of the object; the symbol just provides a shortcut to the jQuery object. The ajax method provides a wide range of options to manage low level Ajax tasks, but we’ll only cover the ones we’ve used here:

  1. url: Should be pretty obvious. This is the web service’s end-point URL. All I’ve done is instead of hard coding it, I assigned the URL to the variable productServiceUrl when I create the page’s HTML from the server side.
  2. type: The type of request we’re sending. jQuery uses “GET” by default. If you quickly take a look again at the SaveProduct operation’s definition, you will notice that on the 1st line it specifies that requests should use the “POST” HTTP method.
  3. dataType: The type of data that the response will send back. The usual types are available like html, json, etc. If you’re working with a SOAP web service, you need to specify the xml dataType.
  4. data: Another easy one. This is the actual data, as XML text, you will be sending to the web service.
  5. complete: The callback delegate that will be executed when the request completes. The callback method must implement the following signature: function (XMLHttpRequest, textStatus) {  /* Code goes here */ } .
  6. contentType: A string representing the MIME content type of the request, in this case it’s “text/xml” because we’re working with a SOAP web service that expects XML data.

Now you’re ready to send your XML data off to the web service. Once the server finishes processing the request, the endSaveProduct method gets called. To process the XML response in jQuery, you need to know the SOAP reponse’s schema/definition. The SaveProduct web method has the following schema:

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <SaveProductResponse xmlns="http://sh.inobido.com/">
      <SaveProductResult>
        <ID>int</ID>
        <Name>string</Name>
        <ManufactureDate>dateTime</ManufactureDate>
      </SaveProductResult>
    </SaveProductResponse>
  </soap:Body>
</soap:Envelope>

From this schema it should be clear that the web method SaveProduct sends back the Product object that was saved. You will find the XML document/data on the xmlHttpRequest parameter’s responseXML property. From here you can use the usual jQuery methods to traverse the XML document’s nodes to extract the data.

Problem: You get an error “Access is denied: [dll name]” trying to deploy a strong named assembly/.dll to the GAC on Windows Server 2008.

"Access Is Denied" error message

"Access Is Denied" error message

Solution:

1. Run the Command Prompt as Administrator and enter the command: explorer %windir%\assembly .

2. Run the Command Prompt as Administrator and enter the command:
explorer [path to directory where the dll is located].

3. Drag and drop the dll from the source directory to the GAC.

That should be it. Your assembly is now deployed to tha Global Assembly Cache. Remember to recycle your web application’s Application Pool, so that the new .dll can be loaded.

InfoPathI recently completed a project based on InfoPath 2007 (Office client version) and Microsoft Office SharePoint Services 2007 (MOSS 2007). Looking back I can say that InfoPath has its uses, but before you build a solution around it you have to be very sure about its limitations. InfoPath has a number of limitations, especially with regards to submitting data, that aren’t that apparent at first sight. If you don’t watch out, you can quickly get caught up in what feels like a never ending maize of dead ends.

InfoPath is often pitched as a solution that doesn’t require writing custom code. This project was no different, and its time lines were made accordingly. In the end we had to write a fair amount of custom code, which was fun, but took more time.

The Many Limitations Of InfoPath DataBase Data Source

InfoPath generally works well viewing standard enterprise data sources such as database tables or SharePoint lists. The limitations become apparent when you attempt to submit to a database using an InfoPath SQL connection, or perform advanced queries. There are a number of limitations when you work with an InfoPath SQL database data source/connection:

  1. Only submit to a single table. This excludes database data sources such as views, and queries with joins. You cannot submit to views or SQL DataSources with joins.
  2. To submit to a database you can only use the main data connection. In other words you can’t have a database-view as the main data source, and setup another simple single table select to submit to.
  3. Range queries are not possible. You can only use a field once in a query’s WHERE clause with an equality operator.
  4. SQL data source dependent on table schema. If a SQL data source’s underlying table is modified, even just adding a column (in other words InfoPath’s SELECT statement doesn’t actually change), the data source will break.
Data Connection Wizard

Data Connection Wizard

With SharePoint lists you cannot query the data source with queryfields like relational data sources.

The above limitations, especially regarding relational data sources, mean one thing: Web services are mandatory for working with your relational data. Using web services allows you to overcome all the limitations of the standard InfoPath SQL data source, and work with a consistent schema.

Another thing to watch out for is that InfoPath’s performance deteriorates quickly when you have more than 50 rows in your result set. Sometimes this figure is much lower. In the project I worked on the data was coming lightning fast from the data base through the web service. But when the data hits the form, and InfoPath starts parsing the XML document, it completely froze for quite a while. I have decided not to torture myself trying to page my form data, so I haven’t looked into this yet (and I believe InfoPath is not meant to be used in this manner). The quickest and most effective solution I could come up with is to allow users to load data into their form incrementally. How this works is that you’ll do a normal retrieve of your data from the data source, but instead of clearing the form, you’ll just add the new result set to the rest of the form’s data. The big drawback of this is that you need to write custom code to modify the XML document directly using XmlWriter: Not a too pleasant exercise.

public void Load_Clicked(object sender, ClickedEventArgs e)
{
  // Call the web service of the secondary DataSource, which will populate it         
  DataSources["ClientWS2"].QueryConnection.Execute();
  var clients = DataSources["ClientWS2"].CreateNavigator().Select("/dfs:myFields/dfs:dataFields/tns:GetClientsResponse/tns:GetClientsResult/tns:Client", NamespaceManager);

  // The 1st time rows are added GetClientsResult might not exist, only GetClientsResponse
  var main = MainDataSource.CreateNavigator().SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetClientsResponse/tns:GetClientsResult", NamespaceManager);
  if (main == null) main = MainDataSource.CreateNavigator().SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetClientsResponse", NamespaceManager);

  using (XmlWriter writer = main.AppendChild())
  {
    // Make sure we are adding Client elements to /dfs:myFields/dfs:dataFields/tns:GetClientsResponse/tns:GetClientsResult and not, /dfs:myFields/dfs:dataFields/tns:GetClientsResponse
    if (main.LocalName == "GetClientsResponse")
    {
      // So if it doesn't exist, create it first
      writer.WriteStartElement("GetClientsResult", "http://sh.inobido.com/CRM/Service");
    }

    while (clients.MoveNext())
    {
      writer.WriteStartElement("Client", "http://sh.inobido.com/CRM/Service");

      // Select all the client element's child elements
      var fields = proposals.Current.Select("*", NamespaceManager);
      while (fields.MoveNext())
      {
        // Write each element and value to the Main DataSource
        writer.WriteStartElement(fields.Current.Name, "http://sh.inobido.com/CRM/Service");
        writer.WriteString(fields.Current.Value);
        writer.WriteEndElement();
      }

      writer.WriteEndElement();
    }

    if (main.LocalName == "GetClientsResponse)
    {
      writer.WriteEndElement();
    }
    writer.Close();
  }
}

The above event fires when a user clicks the Load button. The trick to load data incrementally is that you need a second DataSource exactly the same as the Main DataSource (they should point to the same data store). Whenever you call DataSource.QueryConnection.Execute() InfoPath will wipe any previous data from that DataSource, and reload it with the new data. That’s why you need a separate second DataSource that you call Execute on, and then copy that data to the Main DataSource. The end result is the Main DataSource doesn’t lose its data, but data gets added to it on each query.

Just another side note on InfoPath: Pivot tables are not possible, because you have to know exactly which columns your binding to at design time, and cannot create columns dynamically at runtime. This shouldn’t be a show stopper to most projects, but I’m just mentioning it. All the InfoPath forms we had to do came from Excel spreadsheets, and the one spreadsheet was a monster pivot table.

Hacking The DataConnection

It’s possible to query a data connection directly from InfoPath, change the SQL command dynamically, or extract the connection string. The biggest drawback of this hack (apart from being a hack, i.e. not recommended) is that it requires FullTrust and Sql Code Access Security (CAS) permissions. That means you have to certify your InfoPath form, or create an installer so users have to install it locally onto their machines. This doesn’t really work well when the form is made available to users through a SharePoint document library.

Anyways, here is a very unrefined sample to achieve this:

private const string CONNECTION_STRING = "Server={0};Database={1};User ID={2};Password={3};Trusted_Connection=False;";

private string GetConnectionString(AdoQueryConnection queryConnection)
{
  var password = GetConnectionStringParameter(queryConnection, "Password");
  var user = GetConnectionStringParameter(queryConnection, "User ID");
  var server = GetConnectionStringParameter(queryConnection, "Data Source");
  var db = GetConnectionStringParameter(queryConnection, "Initial Catalog");
  return string.Format(CONNECTION_STRING, server, db, user, password);
}

// Hmmm, if your using my wonderful hack, then you might want to
// consider rewriting this method to use regular expressions instead ;-)
private string GetConnectionStringParameter(AdoQueryConnection queryConnection, string name)
{
  var paramIndex = queryConnection.Connection.IndexOf(name + "=");
  var parameter = queryConnection.Connection.Substring(paramIndex, queryConnection.Connection.IndexOf(";", paramIndex) - paramIndex);
  return parameter.Substring(parameter.IndexOf("=") + 1);
}

private IDataReader SelectWorksheetItems(SqlConnection connection, int pocketID)
{
  using (var dbCommand = new SqlCommand("WorksheetItemGetByPocket", connection))
  {
    connection.Open();
    dbCommand.Parameters.Add("@pocketID", SqlDbType.Int).Value = pocketID;
    dbCommand.CommandType = CommandType.StoredProcedure;
    return dbCommand.ExecuteReader();
  }
}

worksheetItemCurrentDS = DataSources["WorksheetItemCurrent"];
worksheetItemCurrentCmd = ((AdoQueryConnection)worksheetItemCurrentDS.QueryConnection).Command + " where \"PocketID\"={0}";

using (var connection = new SqlConnection(GetConnectionString((AdoQueryConnection)worksheetItemCurrentDS.QueryConnection)))
{
  using (var reader = SelectWorksheetItems(connection, 24))
  {
    // Do some stuff with the DataReader here...
  }
}

InfoPath’s different data sources each use a specific data connection that inherits from the abstract class Microsoft.Office.InfoPath.DataConnection. The main point of the above example is that you can cast your InfoPath’s DataConnections to its specific implementation. For SQL database data sources InfoPath uses AdoQueryConnection. With AdoQueryConnection you have the ability to extract or manipulate the data source’s command and connection string.

Using SQL Server To Store InfoPath Documents

You cannot call store procedures directly from InfoPath, but if you develop on SQL Server 2005 or later, you can use SQL Web Services to call stored procedures as a web service. The big catch here is that SQL authentication and SQL Web Services don’t really go well together. Therefore when using SQL authentication for your InfoPath DataConnections you will either have to support integrated authentication for calls coming through the SQL Web Service (and SQL authetication for direct calls from the InfoPath form), or you will have to throw open access to your stored procedure to all users. If your using SQL authentication, there’s usually a good reason your doing so, so additionally supporting integrated authentication might not be an option. Giving access to anyone is an even worse idea.

CREATE ENDPOINT ClientInsertEndpoint
STATE = STARTED
AS HTTP
(
  SITE = 'ServerName',
  PATH = '/WebServiceName',
  AUTHENTICATION = (NTLM),
  PORTS = (CLEAR)
)
FOR SOAP
(
  WEBMETHOD 'ClientInsert'
  (
    NAME = 'DataBase.dbo.ClientInsert',
    SCHEMA = DEFAULT,
    FORMAT = ROWSETS_ONLY
  ),
  WSDL = DEFAULT,
  BATCHES = DISABLED,
  DATABASE = 'DataBase'
)
GO

If is possible to support SQL authentication for SQL Server Web Services, but this requires a SSL server certificate. Microsoft also plans to remove this feature from SQL Server in future releases.

“This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.”

Definitely read Microsoft’s best practices for SQL Server Native XML Web Services.

Finally, you can use SQL Server 2005’s XML data type to save an InfoPath Form or query it in a relational format. Here’s a sample stored procedure that takes in the root node of the InfoPath’s XML document, and inserts the items into a table:

ALTER PROCEDURE [dbo].[ClientUpdate]
(
  @clientsXml XML
)
AS
  INSERT INTO  Client (FirstName,
               LastName,
               CellNo,
               TelNo,
               WorkNo)
SELECT         Clients.Client.query('data(@FirstName)').value('.', 'VARCHAR(25)') as FirstName,
               Clients.Client.query('data(@LastName)').value('.', 'VARCHAR(25)') as LastName,
               Clients.Client.query('data(@CellNo)').value('.', 'VARCHAR(25)') as CellNo,
               Clients.Client.query('data(@TelNo)').value('.', 'VARCHAR(25)') as TelNo,
               Clients.Client.query('data(@WorkNo)').value('.', 'VARCHAR(25)') as WorkNo
FROM           @clientsXml.nodes('declare namespace d="http://schemas.microsoft.com/office/infopath/2003/ado/dataFields namespace dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"; //d:Client') Clients(Client)

The new SQL XML syntax is a bit tricky, but once you get it right it works wonderfully well.

XPath Expressions Are Your Friend

Conditional Format

Conditional Format

Conditional formatting and XPath expressions are very handy to display unique values in a RepeatingTable. For instance say you’ve got a Client object, with multiple Addresses – street, postal, and work. Say you only wanted to show a client’s name once, and list each of his addresses without repeating his name. When you’re using a SQL DataSource, you will do a left join with the address table from the client table. This means you’ll repeat the same client name for each address.

To solve the aforementioned you need to make sure you order by client name, and then hide the textbox with a XPath expression:

tns:ClientName = preceding-sibling::tns:Client/tns:ClientName

What this expression is saying is that if the current Client’s ClientName is the same as the previous Client’s, then do something. That something is the action you’ll check on the Conditional Formatting window, that will be “hide” in our case.

This approach can be extended to multiple fields. All you have to do is make sure your order sequence is correct. So just by ordering your resultset corrrectly and using the right XPath expression, you’ll achieve quite a bit without having to write code.

InfoPath And Visual SourceSafe Does Not Play Well Together

If you’re creating InfoPath forms with Visual Studio Tools for Office and using Visual SourceSafe for source control, you will quickly get a whole range of different and meaningless error messages. Here are the general things to do to resolve them:

  1. Make sure all files in your Visual Studio InfoPath project’s “InfoPath Form Template” directory are checked out, before doing any work on manifest.xsf (the InfoPath form).
  2. If you’re having trouble checking files out of SourceSafe, from within Visual Studio:a. Close Visual Studio.b. Open the Visual SourceSafe application, and check out the files for the project from there. Once you’ve done this you can close Visual SourceSafe.c. Make the directory “InfoPath Form Template” and all its content writeable, by unchecking the Read-only option from the folder’s Options.d. Reopen Visual Studio, and continue working as usual.

Most Annoying InfoPath Deployment

Another aspect of InfoPath you need to consider is how you’re deploying your forms. To deploy a form you need to manually, that’s right manually, update each DataConnection to point to your production environment. Ouch! If you have say 5 forms, with 5 DataConnections each, then your looking at 25 DataConnections to manually update. Nasty! And if you mess one connection up, you’ve got a problem.

SQL DataConnections are the worst to update. When you want to change to a new DataBase, InfoPath completely clears your original select statement and forgets which table you were using, and you have to reselect the columns/table. Should your DataSource’s schema change (i.e. your select statement is not exactly the same as previously), InfoPath will do you the favor of removing your controls’ databindings. Most of the time you’ll probably use all the table’s columns, but you still have to go and re-select that table.

Web Service DataConnections are the easiest to reconfigure (but still pretty painful). You can just take the URL of the new web service, and copy it into the web service address box, and quickly click Next through the DataConnection wizard. InfoPath doesn’t forget which web method your DataConnection uses, like it does with SQL table DataConnections.

The aforementioned makes it extremely time consuming and error prone to deploy InfoPath forms between development, QA and production environments.

Conclusion

  1. Use web services to retrieve and save form data, and plan accordingly. I cannot state this enough. Yes, maybe for the simplest of simple forms you can get away with using InfoPath’s SQL DataConnection (and I mean really simple), but for everything else a web service is an absolute must.
  2. Try to avoid large editable, repeating data grids (or referred to as a RepeatingTable in InfoPath lingo). Be extra cautious when you’re planning on editing large result sets, with lots of drop down lists and lookup data. Forms that work best are ones that displays and edits a single entity, and apposed to forms that edit multiple instances of an entity on the same form.
  3. Don’t think you’re going to deploy those 5 forms in a few minutes. Give yourself enough time for the deployment, and to test each form afterwards to check that you didn’t mess a DataConnection up.
  4. Do a quick prototype of your forms to check whether InfoPath can really handle it. In my case the person who recommended InfoPath for the solution should have checked that it can accommodate pivot tables. This is general good software dev practice, but I think because of all InfoPath’s restrictions, I think one needs to be particularly careful.We’ve gotten so used to having control over every element of the user interface with ASP .NET and Windows Forms that we expect the same of other technologies we use. Remember InfoPath’s controls and their behaviour dictate how your information is displayed. You do not have access to the underlying API that these controls are based on. In other words know what InfoPath’s UI controls can do, because you won’t be able to write your own.

Visual Studio’s Deployment Projects are quite limited. To get them to do more complicated setup tasks require writing custom deployment actions in C#. The problem with writing code is that it places an additional maintenance and testing burden on the developer. Often all that’s needed is to perform a few small operating system tasks. In these scenarios it just feels unjustified to revert to writing a bunch of C# setup logic.

I recently ran into such a scenario. As part of the deployment application, SQL Server 2005 Express had to be automatically unpacked. When the SQL Server Express setup utility is runned with the /x argument, it unpacks its contents, instead of installing SQL Server. The trick is how to execute this shell command with the minimum effort? The answer is to write a little Visual Basic script file (.vbs) that uses the WScript.Shell object. The emphasis is on little. I wouldn’t recommend sticking huge complicated installation logic in a script file. When you have lots of setup logic, then it’s time to write those C# custom actions, together with unit tests, and mocks. But for all those 1 liner shell commands, a script file is just the thing you need.

Visual Basic Scripts (.vbs) Are Your Friend

The VB script:

Set WshShell = CreateObject("WScript.Shell")
WshShell.Exec(Property("CustomActionData") & "\SQLEXPR32.EXE /x:""" & Property("CustomActionData") & "\SQLEXPR2005""")
Set WshShell = Nothing

The Windows Script Host (WScript.Shell) object has two candidate methods to execute commands – Run and Exec. According to Microsoft, if you need access to command-line output, you should use the Exec method instead. In this case I did not specifically need access to shell output, but for whatever reason I was unable to get Run to work.

customactionproperties

Each custom action has access to the CustomActionData argument. This handy little argument is set on the custom action’s properties. It allows you to pass through the directory where the application was installed, using the global variable [TARGETDIR].

WScript.Shell.Exec allows you to execute any standard command line argument in a manner similar to using the Run… dialog box from the Start menu.

visualstudiodeploymentprojectWhat’s nice about this solution is that it allows you to package SQL Server Express with your solution in one file, and then unpack it during the installation process. The other option is to unpack SQL Server beforehand and add the individual files to your deployment solution. If you’re using Visual SourceSafe, you will run into problems with some of SQL Server’s files that have very long names, and are not DOS compatible.

Bioinformatics Comes To .NET

December 23, 2008

My interest in molecular biology grows with each issue of Scientific American and each Technology Review post I read.  For a C# and Java developer, such as myself, Bioinformatics is a natural progression from programming into cell biology. I’m also a big open source proponent. So what do you get when you throw all these together? An open source project that brings the popular BioJava bioinformatics library to .NET, where I’m the latest team addition. BioSharp is the first open source project that I am actively working on.

BioSharp was started by Doug Swisher out of curiosity about how BioJava was implemented. Since .NET lacked an equivalent framework, Doug decided to create a port of BioJava in C# to aid his learning.

Currently I’m converting the classes from the org.biojava.ontology package to the BioSharp.Core.Ontology gene ontology namespace. As a non-native English speaker, the term ontology was new to me, and immediately caught my attention. So I spontaneously started working  on BioSharp’s gene ontology.

It turns out implementing the gene ontology library requires more knowledge about parsing files and building hierarchies of related terms (which could be any term not just biological terms) than knowledge about genes and cells. This suits me very well at this early stage, since my knowledge of cellular biology is extremely limited. I’m definitely working on BioSharp out of enthusiasm for molecular biology, rather than being an expert at anything biology related.

Commercially I develop contracted software for clients based on the .NET platform, and C#. During my ‘free time’ I work on an application based on Java technologies (Java, Spring, Hibernate, and GWT). Sometimes I wish I could use one language for both my .NET and Java development. In the past this lead me to consider using J# for some of my .NET development, but somehow I never got around writing anything in J#. I finally lost all interest when Microsoft dropped J# from the .NET framework. So it was with great interest that I watched the rebirth of an open source J#, called Ja.NET.

Ja.NET is Java 1.5 Standard Edition (J2SE) that compiles MSIL for .NET. Ja.NET is derived from the Apache Harmony JVM. What this means is that all code written for Ja.NET can be compiled to .NET MSIL or Harmony Java bytecode. So far the developers have successfully built and ran JUnit, Xerces, Ant, and other OSS on .NET without any code changes to those distributions. Pretty neat!

One of the most useful features of Spring.NET is its Aspect Oriented Programming (AOP). Object Orientation (OO) decomposes an application into a hierarchy of entities linked through references. AOP on the other hand, decomposes an application into ’service layers’ (referred to as aspects or cross cutting concerns in AOP lingo). This allows us to transfer infrastructure code out of our core business logic and entities. AOP has some really confusing jargon, like advice, weaving, crosscutting concern, joinpoint, pointcut, etc. To get a grip of these basic building blocks of AOP I refer you to Spring’s excellent documentation that will get you started in no time.

This post is for those of you that covered the basic concepts and terms of AOP, and Spring.NET AOP in particular, but are still struggling a bit to put it all together. I’ll give an overview of how all the different parts of AOP come together, and then follow it up with a working example.

Transparently Wrapping Infrastructure Around Objects

Even after going over the fundamentals of AOP can one still be confused. So let’s start of with two very simplified diagrams that contrast OO against AOP. These diagrams are not ment to be technically accurate, just demonstrate the very high level concept of AOP.

Figure 1

The frist diagram of figure 1 shows how all of OO’s operating logic is contained within an object’s methods. In OO the object (or class) is the main construct that distills data (properties) and tasks (methods) into a type of entity. Each class has several methods, and in turn each method consists of business and infrastructure logic. Before we move on, I’d just like to mention that it’s not a case of AOP vs OO, and which one is the better than the other. AOP complements OO, and improves the quality and adaptability of OO.

OO works wonderfully when we only consider data, methods, and statements directly related to the bigger concept they collectively represent. But when we take things like logging, caching, security, and transactions into concideration we get this uneasy feeling that we are adding code that do not have any direct relation to the logical entity. Traditionally we would combine this infrastructure code with our business logic. This results in dirty business logic code, that becomes more complex, confusing, and less maintainable as we increase its coupling with infrastructure code. Not only this, but let’s say you quickly wanted to cache the results of several methods, without modifying each object’s method? You would have to go and manually duplicate the same code in each method were you want to perform the caching. That’s a lot of hard coding labor, and even harder maintenance should you want to change the way you do things.

Along comes AOP that allow you to move the infrastructure code out of our object’s methods into aspects that has specific roles with tasks. So you’ll have an aspect that provides security around methods, and another logging method execution. Our object’s business logic does not have to know anything about the infrastructure code in which it’s embedded. The infrastructure code is dynamically injected before or after a method executes. That is what the second diagram of figure 2 demonstrates: We have our object, and dynamically we specify when, and how infrastructure aspects intercept incoming and outgoing method calls. The result is that we are left with pure business logic code in the object’s methods, which are themselves transparently wrapped in the necessary infrastructure code.

Interfaces And Proxies

Spring.NET’s AOP framework uses proxies and interfaces to transparently wrap objects in aspects. An AOP proxy is an object that intercepts calls to, and results from, our actual business entity objects. The proxy has the exact same public members as our business entity object. When we request an object that we want to wrap in aspects, we actually request its proxy. In our configuration we will tell the proxy which object provides the actual implementation:


<objects xmlns="http://www.springframework.net">

    <object id="crmService" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
<property name="proxyInterfaces" value="Shinobido.GhostBlade.Customers.ICRMService" />
<property name="target">

<object type="Shinobido.GhostBlade.Customers.CRMService, Shinobido.GhostBlade">
<property name="Url" value="http://localhost:2491/CRMService.asmx" />
<property name="UseDefaultCredentials" value="true" />

</object>
         </property>
<property name="interceptorNames">
	<list>
                 <value>impersonationAspect</value>

</list>
        </property>

</object>

     <!-- Interception AOP Begin -->

<object id="impersonationAspect" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
<property name="Pointcut">

<object id="regexPointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="patterns">
	<list>

<value>.*</value>

</list>
                  </property>
               </object>
       </property>
<property name="Advice" ref="impersonationAdvice" />

</object>

     <object id="impersonationAdvice" type="Shinobido.GhostBlade.Security.ImpersonationAdvice, Shinobido.GhostBlade" />

     <object id="Shinobido.GhostBlade.Security.IIdentityProvider"
                    type="Shinobido.GhostBlade.Security.HttpContextIdentityProvider, Shinobido.GhostBlade" />

</objects>
public interface ICRMService
{
    CustomerInformation GetCustomerById( int id ) ;
}

public class CRMService: System.Web.Services.Protocols.SoapHttpClientProtocol, ICRMService
{
    public CustomerInformation GetCustomerById( int id )
    {
            object[] results = this.Invoke( "GetCustomerById", new object[] { id } );
            return ( CustomerInformation )results[0];
    }
}

Figure 2

From the above example we can infer a number of things:

  1. ProxyFactoryObject is going to intercept calls to our target object, CRMService. In Spring.NET there are several proxying strategies to choose from like inheritance or composition (interface) based, autoproxies, and so forth. Here we’re using a GUID-based composition ProxyFactoryObject. When you instantiate this proxy through Spring.NET’s object factory, you’ll notice that the object’s type is actually a runtime generated object of a type like “CompositionAopProxy_4f054a8f2cd349479fe1673d4427aca3″ that implements ICRMService.
  2. ProxyInterfaces expose the members that will be visible to client code and intercepted by the proxy through interface ICRMService. In other words aspects will only be applied to members specified by this interface. Any members specified by this interface will automatically receive advice based on their pointcuts.
  3. Target specifies the business entity object that we’re going to wrap.
  4. InterceptorNames specify that the aspect impersonationAspect must be applied to method requests and outputs.
  5. impersonationAspect’s Pointcut uses a regualr expression that selects all members of the given class to receive impersonationAdvice.

In point 1 I mentioned composition vs inheritance based AOP proxies. We are using a composition based proxy, because the proxy never inherits from our target object, CRMService. A composition based proxy has a private field called m_targetSourceWrapper of type Spring.Aop.Framework.StaticTargetSourceWrapper that stores the actual business entity class we’re redirecting to. An inheritance based proxy inherits from the target object.

Writing A Custom Impersonation MethodInterceptor

Spring.NET provides a number of out-of-the-box aspects for caching, logging, transactions, and exceptions. What we’re going to do is write custom ‘around advice’, called a MethodInterceptor. Remember, Advice are objects that perform the actual work. So logging advice will actually write to the log file. Pointcuts tell the proxy when to pass control to the specified advice. You get four types of advice:

  • Before a target method executes.
  • After a target method executes.
  • Before and after (around) a method executes.
  • When a target method throws an unhandled exception.

The AOP advice we’re going to write, will impersonate the current thread with a WindowsIdentity obtained from an identity provider. This is used when an application runs under a Windows service account, but selected methods need to be called with the current user’s identity, instead of the service account’s. The IIdentityProvider is dynamically injected, and retrieves the WindowsIdentity from the applicable context. For instance when you’re impersonating the current thread in a web application, you need to implement a HTTP IIdentityProvider, that gets the current user’s WindowsIdentity from the HttpContext.

In our specific scenario we are applying impersonationAdvice to all methods (.*) of the ICRMService, implemented by CRMService. In a nutshell, we are impersonating all our calls to CRMService.

Control is passed to an IMethodInterceptor before a target method is entered, and after it returns:

 public class ImpersonationAdvice : IMethodInterceptor
 {   
 #region IMethodInterceptor Members

 public object Invoke( IMethodInvocation invocation )
 {
     using ( IdentityImpersonator.Begin( ObjectManager.New<IIdentityProvider>().Provide() ) )
     {         
         return invocation.Proceed();
     }
 }

 #endregion
 }

ImpersonationAdvice implements IMethodInterceptor. You can almost say that Invoke will replace the target method it’s wrapping. To execute the actual target method, you need to call Proceed() on the supplied IMethodInvocation argument.

Here’s the code for our implementation of IIdentityProvider, IdentityImpersonator, and ObjectManager:

internal class HttpContextIdentityProvider : IIdentityProvider
{
    #region IIdentityProvider Members

    /// <summary>
    /// Provides the identity of the current user.
    /// </summary>
    /// <returns></returns>
    public WindowsIdentity Provide()
    {
        return (WindowsIdentity) HttpContext.Current.User.Identity;
     }

     #endregion
}

public sealed class IdentityImpersonator : IDisposable
{
    #region Globals

    private WindowsImpersonationContext ctx;
    private bool disposed;

    #endregion

    #region Construction       

    /// <summary>
    /// Initializes a new instance of the <see cref="IdentityImpersonator"/> class.
    /// </summary>
    private IdentityImpersonator()
    {
        // Static Construction in Begin().
    }

    #endregion

    #region Public Members

    /// <summary>
    /// Begins this instance.
    /// </summary>
    /// <returns></returns>
    public static IdentityImpersonator Begin(WindowsIdentity identity)
    {
        var impersonator = new IdentityImpersonator {ctx = identity.Impersonate()};
        return impersonator;
    }

    /// <summary>
    /// Undoes this instance.
    /// </summary>
    public void Undo()
    {
        if (ctx != null)
        {
            ctx.Undo();
        }
    }

    #endregion

    #region IDisposable Members

    /// <summary>
    /// Releases unmanaged and - optionally - managed resources
    /// </summary>
    public void Dispose()
    {
        if (!disposed)
        {
            Undo();
            GC.SuppressFinalize(this);
            disposed = true;
        }
    }

    #endregion
}

/// <summary>
/// Instantiates objects based on their name, and provides
/// a standard set of configured utility objects.
/// </summary>
public static class ObjectManager
{
    private static IApplicationContext context;

    /// <summary>
    /// Instantiates a default object with an id/name
    /// that is the same as the class's full name.
    /// </summary>
    public static T New<T>()
    {
        return New<T>(typeof(T).FullName);
    }

    /// <summary>
    /// Instantiates the object with the specified name.
    /// </summary>
    /// <typeparam name="T">The type of object to return.</typeparam>
    ///<param name="name">The name of the object.</param>
    /// <returns>A newly created object with the type specified by the name, or a singleton object if so configured.
    /// </returns>
    public static T New<T>(string name)
    {
        return (T)Context.GetObject(name);
    }

    /// <summary>
    /// Instantiates the object with the specified name, and constructor arguments.
    /// </summary>
    public static T New<T>(string name, object[] arguments)
    {
        return (T)Context.GetObject( name, arguments);
    }

    /// <summary>
    /// Gets the context.
    /// </summary>
    /// <value>The context.</value>
    internal static IApplicationContext Context
    {
        get
        {
            if (context == null)
            {
                lock ( ContextRegistry.SyncRoot )
                {
                    context = ContextRegistry.GetContext();
                }
             }

             return context;
         }
    }
}

ObjectManager serves as the object factory that wraps Spring.NET’s ApplicationContext with some additional functionality. Specifically in this scenario, ObjectManager instantiates our proxied objects.

The important tasks are performed by IdentityImpersonator. HttpContextIdentityProvider supplies IdentityImpersonator.Begin(…) with the current user’s WindowsIdentity from HttpContext.Current.User, which in turn calls WindowsIdentity.Impersonate(). To stop impersonating the current thread, you need to call WindowsIdentity.Undo(). The Dispose method stops the impersonation, so that you need to put code that you want to impersonate, in a using {…} clause. GC.SuppressFinalize(…) tells the garbage collector to ignore IdentityImpersonator’s finalize method, since we already cleaned up the object when it was Disposed.

Usage and Conclusion

So, to impersonate a call to CRMService becomes a completely transparent process. You don’t need to duplicate IdentityImpersonator.Begin() every time you want to impersonate the current thread. The methods that need impersonation is dynamically selected from one place, impersonationAspect’s Pointcut, and the impersonation work is also performed from one place, in ImpersonationAdvice:

var crmService = ObjectManager.New<ICRMService>( "crmService" );
crmService.GetCustomerById( 1 );<

This should clearly demonstrate the power of AOP: Injecting all that functionality into GetCustomerById(…), without adding a single line of code to it, and we can change it all without making any code changes!

I recently completed a very successful project for a client using ASP .NET MVC, Spring.NET and jQuery. One of the technical requirements of the solution was that we wanted to have an advanced validation mechanism that would allow us to move all our validation rules out of theUI layer, and business logic, and into a dynamically configurable rule engine. Spring.NET’s validation framework is ideally suited for this challenging task.

Spring.NET’s validation framework is based on a hierarchy of validation groups, conditions, and actions. I refer those unfimiliiar with Spring.NET’s validation framework, to their well composed documentation.

What I’ll propose here is a way to integrate Spring.NET’s validation with ASP MVC, and some issues you might encounter alng the way.

Spring.NET Validation Is From Mars, and ASP MVC Is From Venus

Okay, so you’ve covered the validation framework’s documentation. You can create new validation rules, pass through an object (in the MVC space this would be the model), and get back a boolean result to tell you whether the object passed (true) or failed (false). As I’ve mentioned this process is made very clear in the help documentation of the validation framework, so I’m going to jump straight into the juicy complexities.

Spring.NET’s validation rules apply themselves directly to a POCO’s (Plain Old C# Object) schema. For instance, say I’ve got a class Customer that I pass through as the validationContext, and I wanted to validate his CellPhone ContactNumber (Customer.ContactNumbers.CellPhone), the validation rule might look something like this:

<v:regex when="ContactNumbers.CellPhone != null and ContactNumbers.CellPhone != ''"
test="ContactNumbers.CellPhone">

When we’re talking about MVC, our Customer will serve as the model sent to a ViewPage by a Controller action.

ASP’s Controller all have a ViewData.ModelState.AddModelError(…), that takes in a key, and an error message. To get MVC to highlight the input element, the key must match its name. To get MVC to automatically bind the HTML control to a model property, the name of the control in turn should be the same as the path to the Property that provides its value. For example, say I want ASP MVC to automatically display his CellPhone number, then I’d use “Customer.ContactNumbers.CellPhone” as the input control’s name. To flag this control as an error source, I’ll use a key with the exact same name.

<%= Html.TextBox( "Customer.ContactNumbers.HomeDialCode" )%>
-
<%= Html.TextBox( "Customer.ContactNumbers.HomePhone" )%>
<%= Html.ValidationMessage( "Customer.ContactNumbers.HomeDialCode" )%>
<%= Html.ValidationMessage( "Customer.ContactNumbers.HomePhone" )%>

The important point is that the naming convention of the ViewPage’s HTML controls, is based on the model’s schema or graph, and so are the validation rules. The trick is then to relate a Spring.NET validation error (and specifically the error message) to the current node in the schema to which it’s being applied.

Spring.NET’s message or ErrorMessageAction has the concept of “providers“. A provider is just a fancy name for an IDictionary<string,IList> of key-values, where the provider name serves as the key, and the list is a list of ErrorMessages. The idea is that each provider name relates to a Spring validation web server control, that will display it’s error. For ASP MVC we’d rather like to generate the correct ModelError key, so MVC can automatically take care of displaying the error message in its own way.

So at this point we have 3 tasks that we need to complete to successfully integrate ASP MVC and Spring.NET Validation:

1. Tell each Spring.NET validation rule where in the object graph it’s currently executing.
2. Generate the correct error key from the validation rule’s location or context.
3. Convert the validation error to a ModelError and add it to the Controller’s ModelState.

Validation Rules: “I Know What I’m Doing, But Not Where I’m Doing It!”

One of the problems of Spring.NET’s validation rules are that they do not know where in the schema they’re executing. Put a another way, they do not know the path that lead to the current rule being executed – henceforth being referred to as their context. Why is this important? It is important because, as explained previously, the MVC’s input field names and error keys are based on the full path of underlying model-object property.

The most straightforward way to provide this contextual information for a validation rule is to embed it directly inside its definition, probably using a custom IValidationAction:

<v:regex id="homeDialCodeValidator" when="HomeDialCode != null and HomeDialCode != ''" test="HomeDialCode">
<v:property name="Expression" value="[0-9]{3}"/>
  <v:action type="Shinobido.GhostBlade.Validation.ModelValidationAction, Shinobido.GhostBlade.Core">
    <v:property name="CurrentError">
      <object id="homeDialCodeError" type="Shinobido.GhostBlade.Validation.ModelError, Shinobido.GhostBlade">
<property name="Key" value="Customer.ContactNumbers.HomeDialCode" />
<property name="Message" value="3 numbers expected." />
      </object>
    </v:property>
  </v:action>
</v:regex>

The problem with the aforementioned approach is that it reduces the re-usability of validation rules. For instance, lets say we have the following classes:

public class ContactNumbers
{
    public string HomeDialCode { get; set; }
    public string HomePhone { get; set; }
}

public class Customer
{
    public string Name { get; set; }
    public ContactNumbers ContactNumbers { get; set; }
    public Spouse Spouse { get; set; }
    public NextOfKin NextOfKin { get; set; }
}

public class Spouse
{
    public ContactNumbers ContactNumbers { get; set; }
}

public class NextOfKin
{
    public ContactNumbers ContactNumbers { get; set; }
}

Ideally we want to create one contactNumbersValidator rule-group, that can be referenced from other validators, wherever ContactNumbers need to be validated:

<v:ref name="contactNumbersValidator" context="Spouse.ContactNumbers" />

The problem with specifying the context information or error key, in the rule, as that it only caters for a single context. For instance, in the above example we would like to validate ContactNumbers from three different contexts: Customer.ContactNumbers, Customer.Spouse.ContactNumbers, and Customer.NextOfKin.ContactNumbers. All three will use the same validation rule, but from different contexts or schema paths. If we specify a context of Customer.ContactNumbers.HomeDialCode, then we are unable to accommodate any other path, such as those for NextOfKin and Spouse.

What we can infer from this exercise is that we need to specify a rule’s context outside of the rule, in a parent group or rule. A validation rule itself cannot contain the context, because it does not know from where it’s referenced. So how do we set the rule’s current context, from its parent?

One of the ValidatorGroup’s overloads for the Validate(…) method, has an input argument called contextParams of type IDictionary. The significance of this argument is that we can write and read values to it – programmatically and from the config file. This allows us to make variables available to validation groups, validators or actions.

So how do we set a variable from the rule configuration? For this we use the “#variableName” syntax of Spring.NET’s expression language. When Spring.NET encounters the following command “#SomeVariable=’SomeValue‘” a new entry is made in the contextParams dictionary with a key name of “SomeVariable” and value of “SomeValue”.

What we’re going to do is write a magic little custom class that allow us to navigate up and down the object graph, as validation rules are evaluated:

public class ObjectContext
{
    private IList<string> contextPath = new List<string>();
    private string finalContext;
    private readonly StringBuilder pathBuilder = new StringBuilder();

    public bool StepIn( params string[] path )
    {
        for ( var i = 0; path != null && i < path.Length; ++i )
        {
            contextPath.Add( path[i] );
        }
        return true;
     }

    public bool FinalStepIn( params string[] path )
    {
        for ( var i = 0; path != null && i < path.Length; ++i )
        {
            if ( i == path.Length - 1 )
            {
                finalContext = path[i];
            }
            else
            {
                contextPath.Add( path[i] );
            }
        }
        return true;
    }

    public bool StepOut( params string[] path )
    {
        // Reverse list so we can start deleting from index 0
        var reversedContextPath = contextPath.Reverse().ToList();
        for ( var i = 0; i < reversedContextPath.Count(); ++i )
        {
            // Just remove the same number of items in "path"
            // from "contextPath"
            reversedContextPath.RemoveRange( 0, path.Length );
        }

        // Revert back to original order and assign back to "contextPath"
        reversedContextPath.Reverse();
        contextPath = reversedContextPath;

        return true;
    }

    public string ContextPath
    {
        get
        {
            if ( pathBuilder.Length > 0 ) pathBuilder.Remove( 0, pathBuilder.Length );

            for ( var i = 0; i < contextPath.Count; ++i )
            {
                pathBuilder.Append( contextPath[i] );

                // If don't have a leaf node, and this is the last
                // intermediate/branch node, then do not add a "."
                if ( string.IsNullOrEmpty( finalContext ) &&
                     i == contextPath.Count - 1 )
                {
                    continue;
                }

                pathBuilder.Append( "." );
            }
            pathBuilder.Append( finalContext );
            return pathBuilder.ToString();
        }
     }
 }

Let’s first explain some of the logic behind ObjectContext. When it comes to object schemas or graphs we can distinguish between three types of contexts: the root context, several intermediate sub contexts, and a final leaf context (containing the “test” expression). The root context serves as the starting point for the evaluation path, and is similar to MVC’s concept of a binding prefix. Sub contexts refer to those that navigate from the root down to a final leaf context. A leaf context is a validation rule end-point, that does not have any children, and contains the actual “test” expression.

ObjectContext has three methods StepIn, FinalStepIn, and StepOut. StepIn allows us to step into a child context, like when we move from Customer into Spouse. FinalStepIn is used when we move from a parent context into a final leaf context, like we’d do if we moved from ContactNumbers to HomePhone. Lastly we have StepOut, that takes us from a child context back up to a parent one, such as when we move back from Spouse to Customer.

All we need to do now, is add a new instance of ObjectContext to contextParams and call the relevant methods as we move through the object graph’s nodes. I wrote a ValidatorGroup extension method to automatically add a new ObjectContext instance to contextParams:

public static class ValidatorGroupExtensions
{
    public static bool Validate( this ValidatorGroup validatorGroup, object validationContext, IValidationErrors errors, bool hasContext )
    {
        var contextParams = hasContext ? new Dictionary<string,object> { { "ObjectContext", new ObjectContext() } } : new Dictionary<string,object>();
        return validatorGroup.Validate( validationContext, contextParams, errors );
    }
}

At this point it should be clear how to add a new instance of ObjectContext to contextParams. What we haven’t discussed is how we’re going to retrieve our ObjectContext instance from contextParams, and invoke one of its methods in the validation configuration. The answer to this question lies in the fact that Spring.NET’s IExpression interface allows multiple independent commands to be executed in the same expression. What’s also important is that we realize that the validation configuration schema’s “when” and “test” attributes are actually IExpression properties. Therefore we can use any of the validation framework’s attributes/properties that is an IExpression to use variables from contextParams:

<v:group id="customerValidator" when="#ObjectContext.StepIn( 'Customer' )">

    <v:condition when="#ObjectContext.FinalStepIn( 'Name' )" test="Name != null and Name != ''" />

    <v:group when="( #ObjectContext.StepIn( 'Spouse', 'ContactNumbers' ); Employer != null )">
        <v:ref name="contactNumbersValidator" context="Spouse.ContactNumbers" />
    </v:group>

    <v:group when="( #ObjectContext.StepOut( 'Spouse', 'ContactNumbers' ); #ObjectContext.StepIn( 'ContactNumbers' ) )">
        <v:ref name="contactNumbersValidator" context="ContactNumbers" />
    </v:group>
</v:group>

<!-- contactNumbersValidator -->
<v:group id="contactNumbersValidator">

    <!-- CellPhone validator -->
    <v:regex when="( #ObjectContext.FinalStepIn( 'CellPhone' ); CellPhone != null and CellPhone != '' )" test="CellPhone">
        <v:property name="Expression" value="[0-9]{10}"/>
        <v:action type="Shinobido.GhostBlade.ErrorMessageContextAction, Shinobido.GhostBlade">
            <v:property name="Message" value="Unexpected format for cellphone number." />
        </v:action>
    </v:regex>

</v:group>

The first “when” validation statement on the group element tells Spring.NET to fetch the value of the DictionaryEntry with key “ObjectContext”. To execute multiple commands in a single IExpression we place the entire expression in brackets, and separate the each sub-expression with a semi-colon. When multiple statements are specified like this, Spring.NET always returns the last statement’s value. This is why our navigation methods all return true: So that the groups are executed by default, relieving us from the burden to add a last additional expression that returns true.

The next step is to create a custom IValidationAction that inherits from BaseValidationAction, that will store our validation rule’s error message, and build the current context’s full path info:

public class ErrorMessageContextAction: BaseValidationAction
{
    /// <summary>
    /// Gets or sets the error message.
    /// </summary>
    public string Message { get; set; }

    protected override void OnInvalid( object validationContext, IDictionary contextParams, IValidationErrors errors )
    {
        var objContext = contextParams["ObjectContext"] as ObjectContext;

        if ( objContext == null ) return;

        var error = new ErrorMessage( null, Message );
        errors.AddError( objContext.ContextPath, error );
     }
 }

BaseValidationAction provides two virtual methods OnInvalid and OnValid, that are called when a rule fails or passes. ErrorMessageContextAction has one property called Message, that is set to the actual error message we wish to display. Our override of OnInvalid uses ObjectContext.ContextPath to build the full path of the current context. This full path will be used as our ‘provider’. ASP MVC’s built-in error message handling magic fulfills the role of validation errors renderer using this ‘provider’.

The last piece of the puzzle is a custom IValidationErrors implementation that will add validation errors to a MVC Controller’s ViewData.ModelState:

public class ModelStateErrors: IValidationErrors
{
    ModelStateDictionary modelState;

    public ModelStateErrors( ModelStateDictionary modelState )
    {
        this.modelState = modelState;
    }

    public void AddError( string provider, ErrorMessage message )
    {
        if ( message != null &&
             message.Parameters != null &&
             message.Parameters.Length > 0 &&
             message.Parameters[0] != null &&
             message.Parameters[0] is string )
        {
            modelState.AddModelError( provider, message.Parameters[0].ToString() );
        }
    }

    public void MergeErrors( ValidationErrors errorsToMerge )
    {
        throw new System.NotImplementedException();
    }

    public IList GetErrors( string provider )
    {
        var modelStateDict = modelState[provider];
        return modelStateDict == null ? null : modelStateDict.Errors;
    }

    public IList GetResolvedErrors(string provider, IMessageSource messageSource)
    {
        throw new System.NotImplementedException();
    }

    public bool IsEmpty
    {
        get { return modelState.Count == 0; }
    }

    public IList Providers
    {
        get
        {
            return modelState.Keys.ToList();
        }
    }
}

Class ModelStateErrors internally wraps a ViewData’s ModelStateDictionary, and automatically adds Spring.NET validation errors to it. The provider name is used as the key for AddModelError, because this is the ‘bucket’ that we’d like to sink the message to. The ErrorMessage’s first parameter is expected to be the message text.

Usage and Conclusion

An important point to remember when specifying the context in Spring’s validation configuration, is to always provide a complete path from the current node to a final leaf node. It is important to StepIn and StepOut of contexts in-sync with the validation rules. If a context is skipped, our we don’t StepOut of a previous one, we will not get the correct path. When you get the wrong context, check that you’ve SteppedOut as many times as you’ve SteppedIn, to bring you back to the current node or level. Also check that you’ve specified the correct context names when you StepInto a context.

All we need to do is make sure our context navigation correctly follows our validation rules. Apart from this we don’t really need to do anything else to get Spring.NET to add its validation errors and messages to ViewData’s ModelState:

1. Import the namespace where the ValidatorGroupExtensions is defined:

using Shinobido.GhostBlade.Extensions;

2. Get the desired ValidatorGroup from Spring.NET’s objects configuration.
3. Call ValidatorGroup.Validate with ModelStateErrors as the IValidationErrors implementation, and hasContext as true.

Just obtain the desired ValidatorGroup from the objects configuration, ModelStateErrors as the IValidationErrors implementation in a Controller’s Action method:

public partial class CustomerController: Controller
{
    public ActionResult EditPersonalAssessment( int id )
    {
        var customer = ObjectManager.New<ICustomer>();
        customer.ContactNumbers = new ContactNumbers
                                  {
                                      CellPhone = "djsk"
                                  };
        customer.Spouse = new Spouse
                          {
                              ContactNumbers = new ContactNumbers
                                               {
                                                   CellPhone = "kasjd"
                                               }
                          };
        var validator = ObjectManager.New<ValidatorGroup>( "customerValidator" );
        var result = validator.Validate( sampleObj, new ModelStateErrors( ViewData.ModelState ), true );
    }
}

From the final usage we observe that it’s a pretty neat way of integrating Spring.NET’s Validation Framework with ASP .NET MVC’s ModelState and error handling magic. The only part that’s a bit weird is the way we specify the context in Spring.NET’s validation configuration. It abuses the IExpression attributes a little in a way that they weren’t originally designed for. But I believe this is a small price to pay to gain the huge benefit of automatic integration of Spring.NET’s Validation Framework and ASP MVC’s validation and error handling and display.

In the next Spring.NET post I’ll be covering how to use Spring.NET’s Aspect Oriented Programming (AOP) to create an impersonation aspect. Happy Springing until then!

A very important factor to determine before writing any unit test, is what its scope should be. In other words a unit test should be written with clear objectives in mind, as to what it’s going to test, and anything outside this scope should be ignored as far as possible. This means that if we would like to verify business rules applied to data, then we should not test anything else. This includes the low level data access methods responsible for returning and transforming the data from the database.

Mocks come in extremely handy in this scenario. They can be used to return generated data from my data access methods that reflect an ideal situation where result-sets are 100% correct. However this creates an overly artificial test setup, which completely ignores the role of data access methods. Mistakes in the underlaying queries also go unnoticed until its too late.

Testing data access code, and including them in the scope of unit tests is a very cumbersome process. Hence I give them very low priority in my unit tests.

The most straightforward option is to follow the following process:

  1. Insert generated objects with the expected initial state.
  2. Fetch the inserted objects from the database, and execute business logic operations on them.
  3. Update the objects.
  4. Re-fetched them again, and delete the returned objects to clean-up the database.

With this approach problems start when unit tests fail midway, and bits and pieces of the broken objects’ state remain scattered across the development database. Over time it gets messy, and often the broken data affects other queries and unit tests. This means that we lose the isolated characteristic of a good unit test, since one unit test can cause unwanted effects in other unit tests through the central database. Very bad indeed.

So what can we do to solve this problem? Luckily Hendry Luk has a whole series on this very problem and how we can solve it. He suggests the following smart ways to test data access code:

  1. In-memory database using Sqlite
  2. Transaction rollback
  3. Restorable file-based DB
  4. Preset state with NDBUnit
  5. Fake DB provider with Linq

My colleague, Riaan Hanekom from NGenerics fame, showed me his perfect code for a singleton in C# .NET (version 2 and later). This generic class can create a singleton for any non-static class that has a default constructor.

This program is licensed under the Microsoft Permissive License (Ms-PL).  You should
have received a copy of the license along with the source code.  If not, an online copy
of the license can be found at http://www.codeplex.com/NGenerics/Project/License.aspx.
*/
public static class Singleton<T> where T:new()
{
private static readonly T instance = new T();
public static T Instance
{
get
{
return instance;
}
}
}
So simple, yet so complete…