Sunday, November 13, 2011

Integrating Spring.NET with ASMX WebServices

In one of the previous post, we saw how easily we can Enable Dependency Injection for Web Forms Web Pages and User Controls.  In this post we will cover the last topic in the Dependency Injection series i.e. Enabling Dependency injection in ASMX WebServices using Spring.NET.

Its not at all difficult to Enable Dependency Injection in ASMX WebServices.  Lets look at the steps we will need to it
  • Configure the Spring Context in web.config
  • Add the Spring WebSupportModule Module to the list of httpModules
  • Configure the WebServiceHandlerFactory to intercept any path that matches the pattern *.asmx
  • Configure the WebService class in spring config file with its dependencies
Let's look at each step in a little more detail.

Step - 1 - Configure the spring context in web.config

First we need to add spring config section handler in the configSections.  The updated web.config looks like
Next we need to add the spring config section in web.config. This section will inform Spring.NET as to where should it look for its configuration file. Add the following section to web.config
Nothing special about the above piece of configuration. We are informing Spring.NET that its configuration file is located in ~/Config/ directory and its called webservice.xml.

Step - 2 - We need to add the Spring WebSupportModule module to the list of httpModules

In this step, we will need to add the WebSupportModule to the list of httpModules in the web.config.  This is how the updated web.config looks like
Step - 3 - Configure the WebServiceHandlerFactory to intercept any path that matches the pattern *.asmx

Again, all we need to do here is add an Handler in the httpHandlers section in web.config. Update web.config looks like
Step - 4 - Configure the WebService class in spring config file with its dependencies

We are almost there. All that is left now is to configure the WebService class in the Spring.NET configuration file webservice.xml.

Let's say that we want to develop a HelloWorld webservice, that has one method called GreetUser.  This method takes in the user name as argument.  We will inject the greeting to be used using Spring.NET.

The code of the HelloWorld webservice looks like


Nothing to explain here, all we are doing is prepending the Greeting Property to the userName passed and returning the value as the result.

Notice that this HelloWorldService class is a POCO and there is nothing web service specific to it.

The spring configuration that will inject the Greeting into the HelloWorldService looks like
Notice that, we are configuring the implementation of WebService with the ID HelloWorldServiceImpl.  However, the actual WebService is exposed via Spring.NET.  The Spring.Web.Services.WebServiceExporter acts as a proxy over the actual WebService implementation.

All set!

Lets run the server and browser the URL which would look like http://localhost:<your-port-number>/HelloWorldService.asmx?op=GreetUser.  This should open up a page which looks like this
Page which will let us invoke the HelloWroldService.GreeUser WebService
This is the page from which we could invoke the HelloWorldService.GreetUser WebService.

Let's type in Git Shah in the user name field and click Invoke.  Here is what we get
As you can see, the greeting message Good Morning was injected in the HelloWorldServiceImpl class via Spring.NET.

That's all folks, we have successfully Integrated Spring.NET with ASMX WebServices!

Sunday, November 6, 2011

Making operator precidence more explicit with NHibernate Linq Provider

Recently, while writing one of the NHibernate queries, using the NHibernate LINQ provider we faced a very interesting problem.

The issue was the NHibernate LINQ provider was not adding appropriate parenthesis to make the operator precedence more explicit.

The query was simple enough, we wanted to get a list of records based on certain condition. Let's say, for the sake of this post, consider that there is an employees table with ID, Name and Salary columns. The DDL to create the employees tables on SQLServer looks like
NHibernate class against which this table is mapped is called Employee. The Employee class and its mapping file looks like
As you can see there is nothing fancy about the table or the mapping.

Let's talk a bit about the query we want to fire against the employees table.  We want to get list of employees whose name equals "Git" OR whose salary is between 1000 and 10000.

The SQL that would do the job for us would look like:

Again nothing remotely fancy about the SQL.

Let's try and write the same query using, NHibernate LINQ provider and lets look at the generated SQL.  The NHibernate LINQ query to get similar results would look like:
The where condition is the exact replica of the SQL where condition that we had seen earlier.  Only difference this time around is, we are using the LINQ syntax.

So far so good, the problem starts when we look at the SQL that is generated. The simplified version of the SQL generated from the above LINQ query looks like

I have removed all the named parameters that NHibernate adds, but essentially the query looks like the one shown above.

Whats wrong with the query? 

Notice that there are no parenthesis to enforce the operator precedence!  Because of this, it might get confusing to identify the order in which the operators will be process.

Consider a case when you have a complex query with many conditions and if proper parenthisis are not applied then it could get confusing.

I tried various permution and combination to force the NHibernate LINQ provider to spitout the parenthesis correctly, however I was not successful in doing so.

Finally, I decided to switch to the QueryOver API provided by NHibernate.  QueryOver API is a Fluent wrapper over the NHibernate Criteria API.  Using the QueryOver API the above code would look like

As you can see the nothing much has changed.  The only changes are, .Query() call has been changed to .QueryOver() and instead of .ToList() we have to call .List().

Let's look at the generated SQL Query:
As you can see, it correctly adds the parenthesis to make the operator precedence more explicit!
Have some Fun!