Sunday 20 July 2014

Null-coalescing operator in C#

It feels like I’ve been using C# forever. When you’ve been doing something for a long time it’s easy to fall into habits and miss or forget about techniques that could make your life a little easier so it doesn’t hurt to remind ourselves of things from time to time.

I have used many DI containers like Spring.Net, Unity, NInject etc. but I recently started using StructureMap for the first time. I added it to an MVC project using NuGet and when I looked at the code that had been added to my project I saw code like this:

protected override IEnumerable<object> DoGetAllInstances(Type serviceType) 
{
	return (this.CurrentNestedContainer ?? this.Container).GetAllInstances(serviceType).Cast<object>();
}

It really struck me that I couldn’t remember the last time I used the null-coalescing operator (??). Some quick revision:

“The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.” [1]

The C# Reference goes on to describe more features of the ?? operator:

  • You can use the ?? operator’s syntactic expressiveness to return an appropriate value when the left operand has a nullable type whose value is null.
  • If you try to assign a nullable value type to a non-nullable value type without using the ?? operator, you will generate a compile-time error.
  • If you use a cast, and the nullable value type is currently undefined, an InvalidOperationException exception will be thrown.
  • The result of a ?? operator is not considered to be a constant even if both its arguments are constants.

So, by way of example, the following statements are all equivalent:

return nullableValue ?? someOtherValue;

return nullableValue != null ? nullableValue : someOtherValue;

if(nullableValue != null)
{
    return nullableValue;
}
else
{
    return someOtherValue;
}

References

Sunday 20 July 2014

Sunday 13 July 2014

Configuring ELMAH to use SQL Server

ELMAH (Error Logging Modules and Handlers for ASP.NET) is a great little project but the documentation could be improved. One thing I like to do is to get ELMAH logging to a SQL Server database pretty much as soon as it’s integrated into a project but the documentation is a bit scant. Here’s how you do it, in this case for an MVC application.

At the time of writing the core ELMAH library is in version 1.2.1 and the Elmah.MVC package is in version 2.1.1.

Install ELMAH

In your MVC application Manage NuGet Packages… and search for ‘elmah’. Install the Elmah.MVC package which will also install the ELMAH core library as a dependency.

image

Create the ELMAH database

Hop over to the ELMAH site and locate the Microsoft SQL Server DDL script on the downloads page. Download the DDL script to your machine.

SNAGHTMLdc8946

Open SQL Server Management Studio and create a database. I called mine Elmah. Open the DDL script and run it against the new database. This will create the tables and stored procedures used by ELMAH.

SNAGHTMLe49de1

Create a SQL login which will be used by ELMAH to connect to the Elmah database from your MVC application. I use SQL Server authentication. You’ll probably want to cancel password policy enforcement etc. if you do the same.

SNAGHTMLe842dc

Create a new User in the Elmah database using the Elmah login. Give the user data reader and data writer roles.

SNAGHTMLea5188 

You will also need to grant execute permissions to the ELMAH stored procedures:

USE Elmah; 
GRANT EXECUTE ON OBJECT::ELMAH_GetErrorsXml
    TO Elmah;
GO 

GRANT EXECUTE ON OBJECT::ELMAH_GetErrorXml
    TO Elmah;
GO 

GRANT EXECUTE ON OBJECT::ELMAH_LogError
    TO Elmah;
GO 

Modify the ELMAH configuration in the MVC application

When you added ELMAH to your MVC application it will have created an elmah section in your Web.config. You will need to update Web.config to include a connection string for the Elmah database and then update the elmah section to use that connection string.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- other configuration removed for clarity -->
  <connectionStrings>
    <add name="elmah" connectionString="server=localhost;database=;uid=Elmah;password=password;" />
  </connectionStrings>
  <!-- other configuration removed for clarity -->
  <elmah>
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="elmah" applicationName="YourApplicationName"/>
  </elmah>
</configuration>

That should be all there is to get started. Now you’ll probably want to secure ELMAH.

Adding bundling and minification to an empty MVC site

If you create an empty MVC application you’ll probably want to add features like bundling and minification. The process is very simple and starts with NuGet.

At the time of writing MVC is in version 5.

Get the NuGet optimization package

In Visual Studio Manage NuGet Packages…

image 

Search on the term ‘optimization’.

image

Install the Microsoft ASP.Net Web Optimization Framework. Notice that this has dependencies that will also be installed.

image 

Create your bundle configuration class

In the App_Start folder of your application create a new class called BundleConfig. Create a RegisterBundles(BundleCollection bundles) static method in the class which you will use to register your bundles. If you’re not familiar with bundles you’ll probably want to look-up ScriptBundle and StyleBundle from the System.Web.Optimization namespace to see how to do that.

Here’s an example that registers my CSS files:

namespace Mansio.Web.UI
{
    using System.Web.Optimization;

    /// <summary>
    /// This class handles bundle configuration.
    /// </summary>
    public class BundleConfig
    {
        /// <summary>
        /// Registers bundles with the application.
        /// </summary>
        /// <param name="bundles">The bundles to register.</param>
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/*.css"));
        } 
    }
}

Update Global.asax

The final step is to call the bundle configuration from Global.asax by calling your static RegisterBundles method from Application_Start.

/// <summary>
/// Called when the application starts.
/// </summary>
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

That’s all there is to it.

See also