Monday, January 30, 2012

Nice reading about SQL indexing and SQL tuning for developers

My colleagues shared with me a link to an online SQL indexing and tuning tutorial (a guide to database performance by Markus Winand) which I think is worth reading. "Indexed ORDER BY", "Searching for ranges" - those are few sample topics described in the book. Different DBMS are covered - MS SQL, Oracle and others. You can also check your SQL tuning knowledge by taking a short online test.

Saturday, January 28, 2012

The correct way to download text files

Downloading a file - a common task you have to deal in many projects. Generally it is quite simple - all you have to do is to read a file or a string content into memory and dump it into HttpResponse.

public static void DownloadFile(string content, string fileName, bool addBOM)
{
     DownloadFile(System.Text.Encoding.UTF8.GetBytes(content), fileName, addBOM);
}

public static void DownloadFile(byte[] content, string fileName, bool addBOM)
{
     if (content != null)
     {
          byte[] bom = System.Text.Encoding.UTF8.GetPreamble();
          int contentLength = content.Length + (addBOM ? bom.Length : 0);

          HttpContext.Current.Response.ClearHeaders();
          HttpContext.Current.Response.Clear();
          HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
          HttpContext.Current.Response.AddHeader("Content-Length", contentLength.ToString());
          HttpContext.Current.Response.ContentType = "application/octet-stream";
          HttpContext.Current.Response.Flush();

          if (addBOM)
          {
               HttpContext.Current.Response.BinaryWrite(bom); 
          }
           
          HttpContext.Current.Response.BinaryWrite(content);
          HttpContext.Current.Response.End();
     }
}

The example shows how the UTF8 text file should be pushed for download. I believe this is most popular encoding for the text files containing localized data. Couple things to be noted here:
  • Some text editors behave differently while opening UTF8 encoded files with BOM (byte order mark) and without it. This is mostly related to legacy text editors which might handle BOM prefixed files incorrectly. So you might have a requirement to include BOM information into the file you are presenting for download or just skip it. 
  • Adding a content-length header is a very good practice. This provides the client browser with the information required to display download progress correctly. When you have a requirement to download a string content as a file, use the appropriate encoding when calculating content length value. Relying on the string content length is not always the good solution. When you have a UTF8 encoded string all the localized international characters are encoded using 2 bytes, therefor calculating string length in characters would actually cut 1 byte off any international character available in the string.

Saturday, January 21, 2012

Replacing page contents completely using javascript

Let me share with you an example of how it is possible to replace the whole page content using javascript. When this is applicable? One of the situations I have experienced was the requirement to call a third party service returning the whole report content as a HTML page. Report generation was quite a time consuming operation and because of that reason there was a requirement to call the service using Ajax.

The complete solution:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <title>Calling a long running page</title>
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        
        <script type="text/javascript">
            $(document).ready(function () {
                $.ajax({
                    url: "LongRunningPage.aspx",
                    type: "POST",
                    context: document,
                    data: {
                        parameter1: "This is parameter1 value"
                    },
                    success: function (data) {
                        document.open();
                        document.write(data); 
                        document.close(); 
                    }
                });
            }
            );
        </script>

    </head>
    <body>
        <p><img src="ajax-loader.gif" alt="In progress" /></p>
    </body>
</html>

By the way, I highly recommend this site if you need a progress info image for ajax calls.

Monday, January 16, 2012

Extracting WCF bindings

Couple days ago my colleague Rimas and me came across a situation where we needed to add several configuration parameters to some predefined WCF binding. We also wanted to know how those predefined bindings are configured. WCF provides many bindings preconfigured out of the box - starting with BasicHttpBinding moving all the way down to more complex configurations. All of them basically are Binding instances with some predefined set of configuration parameters which we were interested in.

One of the easiest ways to see what's inside the binding is to add a service reference using Visual Studio. It  generates a proxy class and configures client to use the service so the binding information gets pushed into *.config file.

Generating configuration parameters for all WCF bindings at once is a bit more complex task. We solved it this way:

static void Main(string[] args)
{
    string sectionName;
    string configName;

    var types = Assembly.Load("System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
        .GetTypes()
        .Where(t => t.IsSubclassOf(typeof(System.ServiceModel.Channels.Binding)))
        .Where(t => !t.IsAbstract)
        .Where(t => t.GetConstructor(Type.EmptyTypes) != null)
        .ToArray<Type>(); 

    var generator = new ServiceContractGenerator(
        ConfigurationManager.OpenMappedExeConfiguration(
            new ExeConfigurationFileMap() { ExeConfigFilename = "Bindings.config" }, 
            ConfigurationUserLevel.None));

    foreach (var type in types)
    {
        generator.GenerateBinding(Activator.CreateInstance(type) as System.ServiceModel.Channels.Binding, out sectionName, out configName); 
    }

    generator.Configuration.Save(); 
}

Saturday, January 7, 2012

ASP.NET MVC 3 controller action method parameter binding

When I started to play around with ASP.NET MVC one of the areas I needed more light to be shed on was controller action parameter binding. At the first glance the binding behaviour looked like "you name it - you get it" which seemed kind of suspicious. As appeared later there was not so little truth in the rule mentioned earlier.

In a very basic manner there are two classes involved in executing a controller action method and binding parameters. ControllerActionInvoker is a class responsible for finding an appropriate controller class action method by matching its signature to a route data (obviously it is not a single task performed by this class). Usually developers would not need to deal with this class directly.

After the appropriate action method is found a DefaultModelBinder class comes into play by managing method parameter binding. And this is were the magic begins.

Parameter values are bound using the data that arrives within a http request. The following request data is used when looking up data to be bound (in the order defined below):

  1. Posted form data
  2. Route data
  3. Querystring data
  4. Submitted file data

Keeping it short for simple action parameter types - action parameters matching request data keys are bound to corresponding request data values. All non matching action parameters are set their default values.

Keeping it short for complex action parameter types - action parameter type public properties matching request data keys are bound to corresponding request data values. All not matching properties are set their default values. Complex type action parameters are always instantiated.

I guess some examples would be a good place to start explaining the rules mentioned above.

A simple untyped view to display a list of product categories would call action like this:

public ActionResult Categories()
{
    ViewData["Categories"] = ProductNH.GetProductCategories();
    return View(); 
}

A corresponding view markup:

@using (Html.BeginForm("Categories", "Product", FormMethod.Get))
{ 
    <ul>
    @foreach (var category in (IList<Category>)ViewData["Categories"])
    {
        <li>@category.Name - @category.Descn</li>
    }
    </ul>
    
    <input type="submit" value="Refresh categories" />
}

Most probably you would notice the html form and the submit button being redundant in this particular situation and you would be absolutely right. But I would like to keep them as it is to stay in sync with my later samples.

Let's add some filtering functionality and update the action method to accept a filter parameter:

public ActionResult Categories(string namePart)
{
    ViewData["Categories"] = ProductNH.GetProductCategories(namePart);
    return View(); 
}

An updated view markup:

@using (Html.BeginForm("Categories", "Product", FormMethod.Get))
{ 
    <label for="namepart">Category name part: </label>
    <input type="text" name="namepart" />
    
    <ul>
    @foreach (var category in (IList<Category>)ViewData["Categories"])
    {
        <li>@category.Name - @category.Descn</li>
    }
    </ul>
    
    <input type="submit" value="Refresh categories" />
}

After the html form is submitted the "namepart" value comes to the server as a query string value (notice the form submit mode FormMethod.Get). It is then matched to the action parameter name (case-insensitive match is performed).

Let's change the form submit mode to FormMethod.Post. In such case the following actions are valid to serve a view request:

[HttpPost]
public ActionResult Categories(string namePart)
{
    ViewData["Categories"] = ProductNH.GetProductCategories(namePart);
    return View();
}

[HttpPost]
public ActionResult Categories(FormCollection formCollection)
{
    ViewData["Categories"] = ProductNH.GetProductCategories(formCollection["namepart"]);
    return View();
}

Next, move a little bit further: let's define a class for a category filter:

public class CategoryFilter
{
    public string NamePart { get; set; }
}

And let's pass it into the controller action:

[HttpPost]
public ActionResult Categories(CategoryFilter filter)
{
    ViewData["Categories"] = ProductNH.GetProductCategories(filter.NamePart);
    return View();
}

What happens here is the CategoryFilter class instance is constructed using default parameterless constructor and property NamePart is mapped to a posted form data value identified by the key "namepart". As you might have already noticed introducing the CategoryFilter class did not require any changes in the view markup. Lovely, isn't it?

Let's make the view to be a typed view and create a model class for it:

public class CategoryListModel
{
    public CategoryFilter Filter { get; set; }

    public IList<Category> Categories { get; set; }
}

In this case changes are necessary for the view markup as well:

@using (Html.BeginForm("Categories", "Product", FormMethod.Post))
{ 
    <label for="filter.namepart">Category name part: </label>
    <input type="text" name="filter.namepart" />
    
    <ul>
    @foreach (var category in Model.Categories)
    {
        <li>@category.Name - @category.Descn</li>
    }
    </ul>
    
    <input type="submit" value="Refresh categories" />
}

Notice the input name changes - it has a "filter" prefix before "namepart". And now the action:

[HttpPost]
public ActionResult Categories(CategoryListModel model)
{
    model.Categories = ProductNH.GetProductCategories(model.Filter.NamePart);
    return View(model);
}

What happens here is the CategoryListModel class instance is constructed using default parameterless constructor. Filter property value is instantiated the same way and its property NamePart is mapped to a prefixed posted form data value. Basically the prefix "filter" is mapped to a property name Filter. The rest of the binding is performed as described in the previous example.

So: you name it - you get it, isn't it so?

Sunday, January 1, 2012

Configure NHibernate SQL logging for ASP.NET web application

Let me share quick instructions for enabling NHibernate SQL logging for ASP.NET web application (default log4net logging). Two steps need to be taken:

  1. Enable log4net logging for your web application. This can be done by putting following line into Global.asax code-behind:
    protected void Application_Start()
    {
        log4net.Config.XmlConfigurator.Configure(); 
        // Other statements suppressed. 
    }
    
  2. Update the web.config file of your web application to enable NHibernate SQL logging to a text file:
    <?xml version="1.0"?>
    <configuration>
        <configSections>
            <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
            ...
        </configSections>
      
        <log4net>
            <appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net" >
    
                <param name="File" value="Logs/log.txt" />
                <param name="AppendToFile" value="false" />
                <param name="RollingStyle" value="Date" />
                <param name="DatePattern" value="yyyy.MM.dd" />
                <param name="StaticLogFileName" value="true" />
    
                <layout type="log4net.Layout.PatternLayout,log4net">
                    <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
                </layout>
            </appender>
    
            <logger name="NHibernate.SQL" additivity="false">
                <level value="DEBUG"/>
                <appender-ref ref="rollingFile"/>
            </logger>
        </log4net>
        
    </configuration>
    
Log file content structure can be customized by changing ConversionPattern parameter value. More information about possible pattern values is available in Apache log4net SDK Documentation.