Mapping a nullable bit column to an enum with NHibernate


I recently had to map an enum with 3 possible values (Pending, Approved, denied) to a nullable bit field in a SQL database. This type of mapping is not supported natively by NHibernate which by default translates enum values to their integer representation. I found several articles on handling the mapping to a string which is pretty straight forward using the … type but I haven’t found anything about this particular scenario.

This is where custom user types come to the rescue and this is what I am going to explain in this article.

To create a custom user type, we just need to create a class that implements NHibernate.UserTypes.IUserType. In our case, the implentation is pretty easy with the only methods that required a little bit of thinking being NullSafeGet and NullSafeSet.
This is how the class looks like:

public class NullableApprovalStatusType : IUserType
{
    public bool Equals(object x, object y)
    {
        return x == null ? y == null : x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    public object NullSafeGet(IDataReader rs, string[] names,
                              object owner)
    {
        bool? dbValue = (bool?) NHibernateUtil.Boolean
                                 .NullSafeGet(rs, names);
        switch (dbValue)
        {
            case true:
                return ApprovalStatusType.Approved;
            case false:
                return ApprovalStatusType.Denied;
            default:
                return ApprovalStatusType.Pending;
        }
    }

    public void NullSafeSet(IDbCommand cmd, object value,
                            int index)
    {
        var obj = (ApprovalStatusType) value;
        bool? dbValue = null;
        switch (obj)
        {
            case ApprovalStatusType.Approved:
                dbValue = true;
                break;
            case ApprovalStatusType.Denied:
                dbValue = false;
                break;
            case ApprovalStatusType.Pending:
                dbValue = null;
                break;
        }
        NHibernateUtil.Boolean.NullSafeSet(cmd, dbValue,index);
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original, object target,
                          object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return DeepCopy(cached);
    }

    public object Disassemble(object value)
    {
        return DeepCopy(value);
    }

    public SqlType[] SqlTypes
    {
        get { return new[] {new SqlType(DbType.Boolean)}; }
    }

    public Type ReturnedType
    {
        get { return typeof(ApprovalStatusType); }
    }

    public bool IsMutable
    {
        get { return false; }
    }
}

Now that we have our custom user type ready we can just do out mapping:

<property name="ApprovalStatus" column="is_approved"
          not-null="false"
          type="MyNamespace.NullableApprovalStatusType,
                MyAssembly" />

It is nice to notice that the custom user type doesn’t have to be in the same namespace or assembly as the mapped class which allows us to keep it in the data access layer and not introduce any NHibernate dependency to the business logic or domain objects.

Advertisements

Unit testing methods with date/time in .net


One of the very important rules of unit testing is to make sure that the result of the test is predictable and repeatable. This is fairly straight forward to achieve in most cases by using constants instead of random values for example but how do we deal with methods using the current date and/or time?

If we just use the DateTime.Now property, the value will change for each test run which will cause us to have unpredictable and sometimes unrepeatable results.

The solution to this problem is pretty simple, create a wrapper class for the DateTime methods that we may need so we can mock the call to methods returning time dependent values.

A very basic wrapper class could look like this:

   1: using System;

   2:

   3: public interface IDateTime

   4: {

   5:     #region Methods

   6:

   7:     DateTime Now();

   8:

   9:     #endregion Methods

  10: }

  11:

  12: public class DateTimeWrapper : IDateTime

  13: {

  14:     #region Public Methods

  15:

  16:     public DateTime Now()

  17:     {

  18:         return DateTime.Now;

  19:     }

  20:

  21:     #endregion Public Methods

  22: }

 

We can now use the DateTimeWrapper implementation of IDateTime in our code and the IDateTime interface can easily be mocked to return a constant value for the Now() method call.

WILT: XML encode a string in .net


Always wondered why I couldn’t find a method that would XML encode a string, effectively escaping the 5 illegal characters for XML. There is such a method but its location in the API is not intuitive at all. It’s in the System.Security namespace:

   1: public static string Escape(

   2:     string str

   3: )

Its usage is:

   1: tagText = System.Security.SecurityElement.Escape(tagText);

This will escape the 5 characters <, >, &, “ and ‘

MSDN: http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape.aspx

WILT: Inherit and Implement in C#


WILT: What I Learned Today

This is a new category of posts I decided to start to record by daily learnings. I am sure that a lot of those posts are going to be embarrassing because they will expose basic things I should have known for a long time but, oh well…
One of the things I enjoy the most with my job is that I learn everyday. Some days I learn about small details, other days I learn more complex techniques or theories.

Anyway, today’s post is about creating a class that both inherit from another class and implements an interface.

This is very straight forward and a frequent occurence but the little “trick” here is to list the inherited class(es) first.

   1: public class MyClassA

   2: {

   3:     ...

   4: }

   5:  

   6: public interface IMyInterface

   7: {

   8:     ...

   9: }

  10:  

  11: public class MyClassB : MyClassA, IMyInterface

  12: {

  13:     ...

  14: }

Flattening the WSDL for WCF services


Windows Communication Foundation is Microsoft’s latest implementation for distributed computing including web-services. One of the key features of SOAP based web services is the WSDL (Web Service Definition Standard) that allows client applications written in any language and running on any platform to discover how to communicate with the services.

In WCF, the WSDL generated for each service uses a feature that is part of the WSDL standard but is not yet widely supported – Import statements. This feature allows to have external files to define sub-sections of the WSDL. This becomes a problem when you are trying to consume a WCF service from systems that have web service implementations that do not support those statements.

This can be fixed by forcing WCF to flatten the WSDL. Christian Weyer wrote a very good article about this so I won’t try to rewrite it because I wouldn’t be able to do it better. Instead, just go and take a look at it for yourself: http://blogs.thinktecture.com/cweyer/archive/2007/05/10/414840.aspx#.

This helped me a lot when trying to make one of my WCF services consumable from Mercator. I hope this can save you some time too.

Processing extension-less files with IIS 6.0 and ASP.NET


The problem

As part of a Single Sign-On implementation with a 3rd party system using SAML 2.0, the user was being redirected to a URL looking like https://mydomain.com/Profile/SAML2/Redirect/SSO?SAMLRequest=&#8230; which is the standard for a Shibboleth implementation of SAML 2.0.

This is all good if you are using a web server such as Apache which doesn’t really care if files have an extension or not and for which URL rewriting is common and easy to implement. The problem with IIS 6, is that the file will not be served by IIS and even if it was, it couldn’t be processed by the ASP.Net ISAPI filter because it doesn’t have an extension registered with this filter.

Solutions

In both cases, IIS needs to be configured to process extension-less files. However, on the ASP.NET side, there are 2 solutions that can be implemented to solve this problem. The first one uses the URL redirect feature of IIS and the second one uses URL Rewriting in ASP.NET. For the end user, both approaches will have the same result but depending on your situation you may want to pick one or the other depending on the implementation and maintenance constraints.

Security and performance warning

The settings described below have both security and performance implications. Therefore, it is important to apply these changes only on the directories or virtual directories at the lowest level possible and not at the website level (unless really necessary).

Solution 1 – Configuring URL redirect in IIS

If a redirection is not an issue, this is the easiest solution to implement. There are several drawbacks to consider:

  • The URL the end user will end on will be different than the original target URL. This is usually just a cosmetic thing and shouldn’t matter much.
  • Some search engines do not like redirects.
  • If there are a lot of extension-less files that need to be accessible through IIS, this will become a cumbersome process because each individual file needs to be configured in IIS. In our particular case, this wasn’t an issue because we had a single file to handle.

You can accomplish this solution with a few steps:

  1. Create an empty file with the name of the target (e.g. SSO)
  2. Upload the ASP.NET version of the file which will be the one processed by IIS (e.g. SSO.aspx)
  3. Right-click on the file from the IIS management console and open the Properties window
  4. Select the A redirection to a URL radio button
  5. Enter the new URL (https://mydomain.com/Profile/SAML2/Redirect/SSO.aspx$Q) in the Redirect to text box. The $Q part of the URL is explained below in the “Dealing with query strings” section
  6. make sure that The exact URL entered above and A permanent redirection for this resource radio buttons are selected

redirect

Dealing with query strings

In our particular case, the URL our users are being sent to contains a query string. If you just enter the URL of the new page to go to, the query string will be lost. To solve this problem, you just append $Q (dollar sign and capital letter Q) at the end of the URL and IIS will substitute it with the actual query string when doing the redirect.

Solution 2 – URL Rewriting

URL rewriting is a little cleaner from the user’s point of view because there is no redirection or URL change on the browser side. In addition to this, it also allows us to create a catch-all solution to be able to process all extension-less files in a directory with a single configuration change. If we add new files, they will automatically be processed in the same way.

Configuring IIS to serve extension-less files

By default, IIS 6 does not process files that do not have an extension. The first step will be to change this behavior by creating a new MIME type. MIME types are created in the HTTP Headers tab of the directory’s or website’s Properties window:

1. click on the MIME Types… button to view the existing MIME Types
http_header

2. Click on the Add… button to create a new MIME type
mime_types

3. Enter the Extension and MIME Type as shown on the screenshot below
image

4. Click OK to close all the MIME windows

Wildcard Mapping

Now that IIS will process extension-less files, we need to make sure that those files are processed by the asp.net ISAPI filter. To do this, we need to create a wildcard mapping.

  1. On the WebSite or Virtual Directory Properties window, go to the Home Directory tab and click on the Configuration… button.
    image
  2. On the Application Configuration window, make sure you are on the Mappings tab and click on the Insert… button in the Wildcard application maps section
    image
  3. Browse to the aspnet_isapi.dll file for the .Net Framework 2.0. Also make sure that the Verify that file exists checkbox is unchecked
    image
  4. Click OK and we are done with this step

URL Rewriting using an HTTPModule

After setting up the extension mapping, all files in that directory will be passed through the ASP.NET processor before being served by IIS but they will not be treated as ASP.NET files because of their lack of extension. If we were to stop here, the actual inline C# or VB.NET code would be served by IIS instead of being processed by ASP.NET.

To resolve this issue, we are going to use a trick called URL rewriting using an ASP.NET feature called HTTP Modules. For this, we need to create the module and then modify our web.config to add the module to the page lifecycle.

The HTTP Module:

   1: using System.Web;
   2:
   3: public class aspneturlModule : System.Web.IHttpModule
   4: {
   5:     public void Init( System.Web.HttpApplication context )
   6:     {
   7:         context.BeginRequest += new System.EventHandler(this.BaseModuleRewriter_BeginRequest);
   8:     }
   9:
  10:     private void BaseModuleRewriter_BeginRequest(object sender, System.EventArgs e)
  11:     {
  12:         HttpApplication app = (HttpApplication)sender;
  13:         string requestedPage = app.Request.RawUrl;
  14:         string appVirtualPath = app.Request.ApplicationPath;
  15:
  16:         if (requestedPage.Length >= appVirtualPath.Length)
  17:         {
  18:             if (requestedPage.Substring(0, appVirtualPath.Length - 1).ToLower() == appVirtualPath.ToLower())
  19:                 requestedPage = requestedPage.Substring(appVirtualPath.Length);
  20:             else
  21:                 requestedPage = string.Format("{0}.aspx?{1}", app.Request.FilePath, app.Request.QueryString.ToString());
  22:         }
  23:
  24:         HttpContext.Current.RewritePath(requestedPage);
  25:     }
  26:
  27:     public void Dispose()
  28:     {}
  29: }

The code presented above is a very simple version of an HTTP Module doing the URL rewriting for our case. This is just to illustrate how such a module would be created but there are a lot of different scenarios that may need to be handled differently.

After building the module, place the resulting library file (e.g. HTTPModule.dll) in the bin folder of the Website or Virtual Directory. If there is no bin folder, create it.

The web.config

We now need to reference this module in the web.config. Open the web.config file and locate the section about httpModules. Then, add our new module like this:

   1: <httpModules>
   2:     […] (other httpModules if any)
   3:     <add type="HttpModule.aspneturlModule" name="HttpModule" />
   4: </httpModules>

We are all set. As opposed to the first solution presented, there is no need to create an empty file without extension and the user will not be redirected to a .aspx file. It all happens behind the scenes.

const vs. static readonly


The problem
I was recently working on an application that relied on a common library stored in the server’s GAC. The application is using constants that are defined in the common library and have different values depending on the environment the application is being deployed to (Dev, Test or Prod). Everything worked fine in our Dev environment but while debugging our code in Test, we found out that it was using the Dev values of the constants instead of the Test values even though the common library stored in the GAC was correct.

Why is it happening?
The cause of this problem is due to the way constants are treated at compile time. Let’s look at the following code:

common.dll
const string MY_CONSTANT = “My Dev value”;

app.exe
if (common.MY_CONSTANT == “My Dev value”) {…}

The .Net compiler substitutes the constant name with its actual value in app so this would actually be equivalent to writing:

if (“My Dev value” == “My Dev value”) {…}

which is the code that will be converted to IL. As a result, it doesn’t matter what the value of the constant is in the dll that has been placed in the GAC because this value will not be read at run-time.

The solution
One of the ways to solve this would be to change the constants values each time the application is being built for a certain environment. This approach creates a build management nightmare and adds complexity when there is no need for it.

A second approach would be to remove the const keyword so the variable is not being substituted for its value at compile time but this would break the design and make for very bad coding practice.

The right way to handle this is to use the static readonly keywords. A static readonly variable can be initialized at declaration time or in a static constructor so the compiler does not know its value at compile time. As a result, there is no substitution and the value will be read at run-time. The fact that the variable is read-only allows to make sure that it has a similar behavior to a constant once initialized.
Besides the added flexibility for initialization, another benefit of a static readonly variable is that it can hold reference types other than string or null as const only can.