Of Code and Me

Somewhere to write down all the stuff I'm going to forget and then need

Use CacheProfile attribute with output caching in asp.net mvc November 22, 2009

Filed under: Asp.Net,C#,MVC,Web — Rupert Bates @ 9:21 pm

I’ve recently been setting up some caching on a new Asp.Net MVC site by using the OutputCache attribute on my controllers:


//cache this for an hour
 [OutputCache(Duration=60 * 60, VaryByParam="")]

This works really well except that it means hard codeding the cache time into my app so if I want to change it I need to recompile and deploy my code which is obviously far from ideal. So I changed my code to load the value from the web.config and ran into this error:

‘An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type’

Not very helpful.

But fortunately there is a better way of doing all this using cache profiles, I just set up a cache profile in my web.config:


<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="HomePage" duration="3600" varyByParam="None" location="ServerAndClient"/>
</outputCacheProfiles>
</outputCacheSettings>

</caching>

</system.web>

And then reference this in my attribute:

 [OutputCache( CacheProfile="HomePage")]

And bingo, we’re sucking diesel as a friend of mine says!

 

Create an Asp.Net MVC HtmlHelper for use in unit tests November 17, 2009

Filed under: Asp.Net,C#,Coding,MVC,Web — Rupert Bates @ 5:47 pm

Here’s a utility factory class to create an HtmlHelper instance so that you can unit test extension methods written on it. It will take a controller and a model for methods which rely on those. I adapted it from this post, and changed it to work with Asp.Net version 1.0 and to accept a model.

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using KableDirect.Web.FrontEnd.Controllers;

namespace KableDirect.UnitTests
{
    class HtmlHelperFactory
    {
        public static HtmlHelper CreateInstance(RouteData route)
        {
            return CreateInstance(route, new HomeController());
        }
        public static HtmlHelper CreateInstance(RouteData route, Controller controller)
        {
            return CreateInstance(route, controller, null);
        }
        public static HtmlHelper CreateInstance(RouteData route, Controller controller, object model)
        {
            HttpContextBase httpContext = new HttpContextDummy();

            var cc = new ControllerContext(httpContext, route, controller);
            var vd = new ViewDataDictionary(model);
            ViewContext vc = new ViewContext(cc, new ViewDummy(), vd, new TempDataDictionary());
            return new HtmlHelper(vc, new ViewDataContainerDummy(vd), new RouteCollection());
        }


        // Dummy classes needed to be able to create HtmlHelper

        private class HttpRequestDummy : HttpRequestBase
        {
            public override string ApplicationPath
            {
                get { return ""; }
            }

            public override string AppRelativeCurrentExecutionFilePath
            {
                // Any shorter string here gives exception:
                // index larger than length of string
                get { return "~/"; }
            }

            public override string PathInfo
            {
                get { return ""; }
            }
        }

        private class HttpResponseDummy : HttpResponseBase
        {
            public override string ApplyAppPathModifier(string virtualPath)
            {
                return virtualPath;
            }
        }

        private class HttpContextDummy : HttpContextBase
        {
            public override HttpRequestBase Request
            {
                get { return new HttpRequestDummy(); }
            }

            public override HttpResponseBase Response
            {
                get { return new HttpResponseDummy(); }
            }
        }

        private class ViewDummy : IView
        {
            public void Render(ViewContext viewContext, System.IO.TextWriter writer)
            {
                throw new NotImplementedException();
            }
        }

        private class ViewDataContainerDummy : IViewDataContainer
        {
            public ViewDataContainerDummy()
            {
            }

            public ViewDataContainerDummy(ViewDataDictionary dataDictionary)
            {
                _data = dataDictionary;
            }

            private ViewDataDictionary _data;
            public ViewDataDictionary ViewData
            {
                get { return _data; }
                set { _data = value; }
            }
        }
    }
}

 

 

Access RouteData for the current Route from a library class in asp.net mvc October 7, 2009

Filed under: Asp.Net,C#,MVC — Rupert Bates @ 1:20 pm

Sometimes it’s useful to be able to access the current RouteData from outside a controller, for instance in a library class. In webforms you could always do


HttpContext.Current

but in Asp.Net MVC it’s a bit less obvious how you get access to this data.

I’ve found the following code works:


RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));

Whether there is an easier way or not I don’t know, but this will do me for now…

 

Group By with Count in Linq September 29, 2009

Filed under: C#,Linq — Rupert Bates @ 8:26 pm

To group a sequence getting a count for each element of the grouped sequence using Linq:

            var wordList = new List<String> { "test", "one", "test", "two" };
            var grouped = wordList
                .GroupBy(i => i) //Group the words
                .Select(i => new { Word = i.Key, Count = i.Count() }); //get a count for each

Which results in this sequence:

watch

 

An Implementation of Fold for C# August 20, 2009

Filed under: C#,Coding,Functional programming,Uncategorized — Rupert Bates @ 9:22 am

I expect there are a number of implementations of this around, but I couldn’t find one so I wrote this. It is an extension method which implements Fold on IEnumerable


public static class Extensions
{
  public delegate TDestination FoldOperation<TSource, TDestination>(TSource item, TDestination acc);
  public static TDestination Fold<TSource, TDestination>(this IEnumerable<TSource> list, FoldOperation<TSource, TDestination> foldOperation, TDestination acc)
  {
     foreach(TSource item in list)
     {
       acc = foldOperation(item, acc);
     }
     return acc;
  }
 }

I can then use this Fold function for something like this which takes an object with a number of properties and creates a querystring with the name/value pairs of all of those properties which are non-null:

public class UrlConstructor
{
  //Takes a RequestParameter object with a number of properties which
  //if their value is set should be translated into querystring parameters
  public static string ConstructUrl(RequestParameters rp)
  {
    //Get all the properties where the value is not null
    var values = typeof(RequestParameters).GetProperties().Where(p => (p.GetValue(rp, null) != null));

    //Fold these values up into a string
    var querystring = values.Fold(((p, acc) => acc + p.Name + "=" + p.GetValue(rp, null) + "&"), "").TrimEnd('&');

    return "http://mybaseurl.com/default.aspx?" + querystring;
  }
} 
 

Enumeration model binder for asp.net mvc August 8, 2009

Filed under: C#,MVC,Uncategorized — Rupert Bates @ 9:06 pm

We were recently working on an asp.net MVC app and I noticed that in a lot of places actions were taking strings as parameters and then converting them to enum values with the action. The reason for doing this rather than just typing the parameter as the enum type was because they were optional and so when the value didn’t exist an error was thrown:

screenshot of error page

screenshot of error page

Because enums are not nullable types they can’t be used as optional parameters.

What was needed then was a way to provide a default parameter for when the parameter didn’t exist in the url. To do this I wrote a custom model binder and it solved the problem pretty well.

Here is the code for the binder

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace EnumTest.Helpers
{
public class EnumBinder<T> : IModelBinder
{
private T DefaultValue { get; set; }
public EnumBinder(T defaultValue)
{
DefaultValue = defaultValue;
}

#region IModelBinder Members
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
return bindingContext.ValueProvider[bindingContext.ModelName] == null
? DefaultValue
: GetEnumValue(DefaultValue, bindingContext.ValueProvider[bindingContext.ModelName].AttemptedValue);
}

#endregion

public static T GetEnumValue<T>(T defaultValue, string value)
{
T enumType = defaultValue;

if ((!String.IsNullOrEmpty(value)) && (Contains(typeof(T), value)))
enumType = (T)Enum.Parse(typeof(T), value, true);

return enumType;
}
public static bool Contains(Type enumType, string value)
{
return Enum.GetNames(enumType).Contains(value, StringComparer.OrdinalIgnoreCase);
}
}
}

And to use it in your project you just register it in your Global.asax, specifying the type of your enum and the default value you want when there is no value available in the input.

protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
            ModelBinders.Binders.Add(typeof(TestEnum), new EnumBinder<TestEnum>(TestEnum.rupert));
        }
 

Functional programming techniques in C# February 11, 2008

Filed under: C#,F#,Functional programming — Rupert Bates @ 9:10 pm

I’ve been reading quite a lot about functional programming recently, as well as playing around with F#, and I’ve found that it is starting to subtly change the way I write code. Recently I was working on an approach to using Linq to Sql with Asp.Net, and I found myself slightly dissatisfied with the following methods:

public static void Insert(TEntity entity)
{
    Insert(entity, false);
}
public static void Insert(TEntity entity, bool submitChanges)
{
    EntityTable.InsertOnSubmit(entity);
    if (submitChanges)
        DataContext.SubmitChanges();
}

public static void Update(TEntity entity)
{
    Update(entity, false);
}
public static void Update(TEntity entity, bool submitChanges)
{
    TEntity original = GetEntity(entity);
    UpdateOriginalFromChanged(ref original, entity);
    if (submitChanges)
        DataContext.SubmitChanges();
}

public static void Delete(TEntity entity)
{
    Delete(entity, false);
}
public static void Delete(TEntity entity, bool submitChanges)
{
    TEntity delete = GetEntity(entity);
    EntityTable.DeleteOnSubmit(delete);
    if (submitChanges)
        DataContext.SubmitChanges();
}

This is pretty straightforward stuff, we have 3 methods Insert, Update and Delete, each of which takes an entity of type TEntity (they are in a generic class) and an overload for each, which also takes a bool to allow client code to specify whether or not to call SubmitChanges on the DataContext immediately. What I dislike about this code is the repeated if statements in each of the overloads, surely there should be a way to refactor those out? This was when a post I’d been reading on Continuation Passing Style popped into my head and I realised that there is, if we use a more functional approach. What we need to do is to create a function ConditionalSubmit() that takes 3 parameters

  • Our TEntity entity
  • The boolean parameter that tells us whether to submit changes or not.
  • A function which will be one our Insert, Update or Delete operations

ConditionalSubmit() can call the function which was passed in, with the entity and then submit the changes or not, depending on the value of the submitChanges parameter. Here is what it looks like:

protected static void ConditionalSubmit(TEntity entity, bool submitChanges, Action<TEntity> operation)
{
	operation(entity);
	if(submitChanges)
		DataContext.SubmitChanges();
}

Now I need to change my implementation of the Insert, Update and Delete methods as follows (I’ve just shown Update for the sake of brevity):

public static void Update(TEntity entity, bool submitChanges)
{
    ConditionalSubmit(entity, x => Update(x), submitChanges);
}

protected static void Update(TEntity entity)
{
    TEntity original = GetEntity(entity);
    UpdateOriginalFromChanged(ref original, entity);
}

The overload without the bool parameter now becomes the version that does all the work, and the overload with the bool passes this version into the ConditionalSubmit() function, using a lambda, along with the other parameters. I think this is a really elegant solution as it abstracts the submit changes functionality away into another function and allows us to get rid of all that repeated code.

Is this really a better solution though? I’m not sure, I think it’s probably just different. In fact in the final code I went back to the original version, purely because I thought it would be easier to understand for the majority of C# developers, and this is code which will need to be used and maintained by others. Having said that I am sure there will be times when a functional approach really does produce a better solution, so I found it very useful to work this through, to get myself to start thinking about coding in a more functional style.

 

A pattern for using Linq to SQL in a multi-tier environment February 8, 2008

Filed under: architecture,C#,Coding — Rupert Bates @ 11:00 am

This post shows an approach for using Linq to Sql within a multi tier Asp.Net application, and particularly how it can be made to work well with ObjectDataSources. It is here as a discussion piece as well as a usable bit of code.

The key features are a Request-scoped datacontext and entity controller classes which provide easy to use Create, Retrieve, Update and Delete (CRUD) operations implemented with Generics. It also discusses the use of DataLoadOptions and approaches to submitting changes back to the database.

Entity Controller classes

Each database entity has an associated controller class which is used to perform common CRUD operations. Specific entity controllers inherit from a generic class GenericController which already implements all the basic Select, Insert, Update & Delete operations.

[System.ComponentModel.DataObject]
public class GenericController<TEntity, TDataContext> where TDataContext : DataContext
{
    public static List<TEntity> SelectAll()
    {
          ...
    }
    public static void Insert(TEntity entity)
    {
        ...
    }
    public static void Update(TEntity entity)
    {
        ...
    }
    public static void Delete(TEntity entity)
    {
        ...
    }
}

Specific controllers then inherit from this by specifying the entity type which they are concerned with as well as the type of the DataContext used, as follows:

//ProductController class
public class ProductController : GenericController<Product, NorthwindDataContext>
{
}

which allows client code such as the following:

   IList<Product> products = ProductController.SelectAll();

The use of Generics means that I don’t need to add any code at all into my ProductController to get all the standard CRUD operations in a fully type safe way. My ProductController class can now be customised to add any further data access methods which are specific to Products, for instance GetByCategoryId().

Request scoped DataContext

The second part of this solution is the request scoped DataContext. This is a pattern that is commonly used with the Hibernate OR mapper as well as elsewhere, and it means that there is only ever one DataContext per Http request which is stored in the HttpContext.Items collection. It is implemented as a protected property of the GenericController class as follows:

        protected static TDataContext DataContext
        {
            get
            {
                //We are in a web app, use a request scope
                if (HttpContext.Current != null)
                {
                    TDataContext _dataContext = (TDataContext)HttpContext.Current.Items["_dataContext"];
                    if (_dataContext == null)
                    {
                        _dataContext = Activator.CreateInstance<TDataContext>();
                        HttpContext.Current.Items.Add("_dataContext", _dataContext);
                    }
                    return _dataContext;
                }
                else
                {
                    //If this is not a web app then just create a datacontext
                    //which will have the same lifespan as the app itself
                    //This is only really to support unit tests and should not
                    //be used in any production code. A better way to use this
                    //code with unit tests is to mock the HttpContext
                    if (_dataContext == null)
                    {
                        _dataContext = Activator.CreateInstance<TDataContext>();
                    }
                    return _dataContext;
                }
            }
        }

Using the HttpContext.Items collection does introduce a dependency on System.Web to your data layer, but I’ve made the decision that since this solution is specifically designed for use in Asp.Net applications, this is acceptable. Checking for a valid HttpContext and then using an static variable if it doesn’t exist gives a bit of flexibility to use the class outside of a web app, for instance in unit tests, although this will produce subtly different results, so mocking the HttpContext would probably be a better approach.

The usefulness of this approach can be seen if you consider a page which uses a number of ObjectDataSources; if we configure our ObjectDataSource to use the DataContext directly then each one will create and dispose of a new DataContext this will not only quickly become a performance overhead, but will also present us with a problem when specifying LoadOptions for the DataContext resulting in more complex, less maintainable code or quite possibly code which doesn’t specify loading options at all.

It should be noted that this approach means that if I have a CategoryController class as well as a ProductController class, both of which inherit from GenericController, both of these classes will use the same DataContext. In other words the DataContext is shared across the whole request, not just by one class type.

DataLoadOptions

Before going any further, we need to look at the thorny issue of DataLoadOptions. As a number of people have noted the way that Linq to Sql works, means that the DataLoadOptions for your DataContext need to be set before any operations are carried out, and cannot subsequently be changed. This means that in my Asp.Net application I will need to set the DataLoadOptions for the whole request somewhere near the start (assuming of course that I need to set DataLoadOptions at all). It also means that my UI or business layer will need to take responsibility for this.

What this means in practice is that in a classic Web forms type app I will probably set the DataLoadOptions in the OnInit event of my page, if I’m using MVC then my controller will do it. I don’t really have a problem with this, particularly in the case of an MVC app as I think this is probably the best place to actually specify how you want your data loading logic to work. I’m interested to hear other opinions on this.

Submitting changes

Another feature of the Linq to Sql architecture is the way that changes are only submitted to the database when the SubmitChanges() method is called on the DataContext. This means that we must either decide at which point to call SubmitChanges() or delegate this responsibility to client code.
To make the classes as flexible as possible any operations which require a call to SubmitChanges (Insert, Update and Delete), are provided with a boolean parameter which specify whether to submit changes immediately or not. There is also an overload of these methods without this parameter which is equivalent to passing true (again this makes use of ObjectDatasources much more straightforward).
The SubmitChanges method of the DataContext is also exposed through the controller class to give Client code the ability to call this explicitly.

The code

You can download the code for this post from CodeGallery

The code consists of 2 projects

  • The data access layer – this is made up of Linq to Sql dataclasses generated from the Northwind database, a class GenericController (discussed above) and two concrete subclasses ProductController and CategoryController.
  • A test web project – this project has one page with a GridView and a FormView which use the data layer via ObjectDataSources to list all the products in the Northwind database, allow editing and deletion of those projects, and insert new products via the FormView.

To run the example project:

  • Download and unzip the release
  • Open the solution in VS2008
  • Change the connection string in the web.config to point to a Northwind database
  • Run the web project

To use the code in your own projects

  • Copy the class GenericController into your Linq to Sql project
  • Create one entity controller class for each Linq to Sql entity, inheriting from GenericController
  • Optionally define any new entity specific data access operations in your entity controller classes
 

 
Follow

Get every new post delivered to your Inbox.