pr0g33k

 collapse all
  1. Four Ways to Version Your MVC Web API

    MSDN defines a WCF Contract as "a collection of Operations that specifies what the Endpoint communicates to the outside world" and that's appropriate considering Dictionary.com defines a contract as "an agreement between two or more parties for the doing or not doing of something specified." Whenever you create a REST endpoint and it gets consumed by a client, you're establishing a contract with that client. REST is all about resources and a Web API is a contract promising that a given resource will exist at the specified URI. Like most things in life, however, things change. When a resource that is the subject of a Web API changes, you have a few options: you can take the position that the behavior of a resource is one of its intrinsic properties, hence if that changes, you really have a different resource and therefore a different URI or you can establish a version for that resource. Since the former requires clients to update their code to take advantage of the new resources and each new resource will exponentially grow and complicate the API, we'll focus on the latter and discuss versioning in this article.

    Now the question becomes, "How do I version my Web API?" There's a lot of debate on this these days. The main debate comes down to identifying the version via the URI versus identifying the version in the header. There are pro's and con's to both. With Microsoft's MVC Web Api, though, you don't have to limit yourself to just one versioning scheme. I'm going to show you four ways to version your Web API within the same project:

    1. URI using Routing Attributes
    2. Custom HTTP Header
    3. HTTP Accept Header with a header parameter
    4. HTTP Accept Header with a Vendor MIME Type

    Project Setup

    Create a new Web Project and call it "Web" with a Solution name "WebApiVersioning." Make sure "Create directory for solution" is checked. Also note that I'm placing the Solution in a folder named "Projects."

    Select the Web API template and click "OK."

    When creating a new project, it's a good idea to update all of the NuGet packages before you get started so take a few moments to do that. As of this date, Web API 2.1 was the main update I installed. Run the project to make sure everything is working properly.

    URI-based versioning

    The templated project gives us a controller named "ValuesController" by default so we'll just work with that. To make it simple for this tutorial, I'm just going to work with the GET actions but everything we do here will apply to the other actions as well. Change the ValuesController class to this:

    namespace Web.Controllers
    {
        public class ValuesController : ApiController
        {
            // GET api/values
            public IEnumerable<string> Get()
            {
                return new string[] { "value1", "value2" };
            }
    
            // GET api/values/5
            public string Get(int id)
            {
                return "value";
            }
        }
    }

    Run the project and click on "API" in the menu (optionally, you can browse to "/help"). You should see this:

    Let's update our ValuesController and add a new version of the API. Then let's use MVC's Route attribute to add a "V1" and "V2" version indicator to the URI's.

    namespace Web.Controllers
    {
        public class Values_V1Controller : ApiController
        {
            [Route("api/v1/values")]
            public IEnumerable<string> Get()
            {
                return new string[] { "value1 (V1)", "value2 (V1)" };
            }
    
            [Route("api/v1/values/{id:int}")]
            public string Get(int id)
            {
                return String.Format("value {0} (V1)", id);
            }
        }
    
        public class Values_V2Controller : ApiController
        {
            [Route("api/v2/values")]
            public IEnumerable<string> Get()
            {
                return new string[] { "value1 (V2)", "value2 (V2)" };
            }
    
            [Route("api/v2/values/{id:int}")]
            public string Get(int id)
            {
                return String.Format("value {0} (V2)", id);
            }
        }
    }

    When you run the project and browse to the API help view, you'll notice the new URI's:

    As you can see, it's quite simple to version using the URI. This way of versioning is very helpful when your clients do not have access to any other means of reaching distinct versions of your API. For example, browsers or other applications that have only a URI address option can easily reach the different versions.

    Versioning in the URI can give your clients the wrong impression, however. According to some of the REST community, a URI defines a distinct resource. In our case, we have two distinct URI's and therefor two distinct resources. This may not be what we're intending.

    It's important to note that, in this tutorial, I'm only changing the data in the ValuesController to distinguish the 2 versions. In reality, it would be the structure of the objects returned that would dictate the need to have a different version. I didn't want to get bogged down in creating a complicated scenario. Instead, I'm just focusing on several mechanisms to enable versioning.

    Using a Custom HTTP Header

    With Web API 2 and above, you can add custom constraints to your routes. A custom route constraint enables you to prevent a route from being matched unless some custom condition is matched - in this case, the value of a custom HTTP header. The official samples list on Codeplex has a custom Route Constraint that does exactly what we need.

    First, add a new Class Library project called "Core.Web." Be sure to add it to the Projects directory, at the same directory level as the WebApiVersioning solution:

    Add a folder to the Core.Web project called "Routing" and add the Microsoft Web API 2.1 Core Libraries (or whatever is the most recent version) from NuGet.

    Next, add the following classes:

    namespace Core.Web.Routing
    {
        public class VersionConstraint : IHttpRouteConstraint
        {
            private const Int32 DEFAULT_VERSION = 1;
    
            public VersionConstraint(Int32 allowedVersion)
            {
                AllowedVersion = allowedVersion;
            }
    
            public Int32 AllowedVersion
            {
                get;
                private set;
            }
    
            public Boolean Match(HttpRequestMessage request, IHttpRoute route, String parameterName, IDictionary<String, Object> values, HttpRouteDirection routeDirection)
            {
                if (routeDirection == HttpRouteDirection.UriResolution)
                {
                    Int32 version = GetVersionHeader(request) ?? DEFAULT_VERSION;
    
                    if (version == AllowedVersion)
                        return true;
                }
    
                return false;
            }
    
            private Int32? GetVersionHeader(HttpRequestMessage request)
            {
                String versionAsString = String.Empty;
                IEnumerable<String> headerValues;
    
                if (request.Headers.TryGetValues("api-version", out headerValues) && headerValues.Count() == 1)
                    versionAsString = headerValues.First();
    
                Int32 version;
    
                if (!String.IsNullOrEmpty(versionAsString) && Int32.TryParse(versionAsString, out version))
                    return version;
    
                return null;
            }
        }
    }
    
    namespace Core.Web.Routing
    {
        public class VersionedRoute : RouteFactoryAttribute
        {
            public VersionedRoute(String template, Int32 allowedVersion)
                : base(template)
            {
                AllowedVersion = allowedVersion;
            }
    
            public Int32 AllowedVersion
            {
                get;
                private set;
            }
    
            public override IDictionary<String, Object> Constraints
            {
                get
                {
                    var constraints = new HttpRouteValueDictionary();
                    constraints.Add("version", new VersionConstraint(AllowedVersion));
                    return constraints;
                }
            }
        }
    }

    Add a Solution reference to the Web project for Core.Web and update the the Values_V1Controller and Values_V2Controller to this:

    namespace Web.Controllers
    {
        public class Values_V1Controller : ApiController
        {
            [VersionedRoute("api/values", 1)]
            [Route("api/v1/values")]
            public IEnumerable<string> Get()
            {
                return new string[] { "value1 (V1)", "value2 (V1)" };
            }
    
            [VersionedRoute("api/values/{id:int}", 1)]
            [Route("api/v1/values/{id:int}")]
            public string Get(int id)
            {
                return String.Format("value {0} (V1)", id);
            }
        }
    
        public class Values_V2Controller : ApiController
        {
            [VersionedRoute("api/values", 2)]
            [Route("api/v2/values")]
            public IEnumerable<string> Get()
            {
                return new string[] { "value1 (V2)", "value2 (V2)" };
            }
    
            [VersionedRoute("api/values/{id:int}", 2)]
            [Route("api/v2/values/{id:int}")]
            public string Get(int id)
            {
                return String.Format("value {0} (V2)", id);
            }
        }
    }

    Now, run the project and open Fiddler. Switch Fiddler to the Composer tab and type the URI for the Values controller ("http://localhost:[YOUR PORT]/api/values"). In the "Request Headers" box, add "api-version: 1":

    Next, click the "Execute" button. You should have a response in the grid on the left. Select the response for "/api/values" and switch to the "Inspectors" tab. In the bottom half of the Inspectors tab, select the JSON tab. It should look like this:

    Now switch back to the Composer tab and change the "api-version" to 2. Execute it again, select the new response, and look at it in the Inspectors tab.

    If you take a look at the API help view, you'll notice that the routes defined in the VersionedRoute attributes appear only with Values_V1:

    It will be important for you to add your own documentation to let your clients know they can optionally set the "api-version" custom header to access the other versions. Another thing to consider is that you might want to name the first version of your controller without the "_V1" and start naming the subsequent versions with "_V2". This way, the subject of your API's (e.g. "Values" in this case) appears to stay the same from version-to-version (e.g. "/api/values") for the majority of the requests only to be differentiated by the headers.

    Using a HTTP Accept Header with a header parameter

    A lot of people favor using the HTTP Accept header to request the version of the resource. The HTTP Accept header defines the Content-Types that are acceptable for the response. Or, in other words, it is a way for a client to specify the media type of the response content it is expecting. Examples are "text/plain," "image/jpeg," "application/xml," and "application/json." The HTTP Accept header optionally allows you to add parameters to define other aspects of the request. We're going to use "version=[SOME NUMBER]" as a parameter to specify the version we want.

    Update the GetVersionHeader method of the VersionConstraint class to this:

    private Int32? GetVersionHeader(HttpRequestMessage request)
    {
        String versionAsString = String.Empty;
        IEnumerable<String> headerValues;
    
        if (request.Headers.TryGetValues("api-version", out headerValues) && headerValues.Count() == 1)
            versionAsString = headerValues.First();
        else
        {
            var accept = request.Headers.Accept.Where(a => a.Parameters.Count(p => p.Name == "version") > 0);
    
            if (accept.Any())
                versionAsString = accept.First().Parameters.Single(s => s.Name == "version").Value;
        }
    
        Int32 version;
    
        if (!String.IsNullOrEmpty(versionAsString) && Int32.TryParse(versionAsString, out version))
            return version;
    
        return null;
    }
    

    Now run the project and open Fiddler again. This time, add an Accept header for "application/json" and a parameter of "version=1"

    Execute the request and examine the result in the Inspectors tab like you did previously.

    Now let's change the request to XML. Replace the "Accept: application/json;version=1" header with "Accept: application/xml;version=2" and execute the request. The result in the Inspectors tab should look like this:

    Using a HTTP Accept Header with a Vendor MIME Type

    Many in the REST camp do not like to use the generic MIME Types to request a resource (e.g. "application/xml"). Their argument is that they aren't requesting any ol' resource, they're requesting a resource with a specific schema or representation. Vendor MIME Types provide a way to specify the resource in a more granular way. Personally, I'm not a fan of custom Vendor MIME Types. It feels like a solution in search of a problem. But, for those of you that want to go this route, here's a way to implement versioning for these types of requests.

    Update the GetVersionHeader method of the VersionConstraint class to this:

    private Int32? GetVersionHeader(HttpRequestMessage request)
    {
        String versionAsString = String.Empty;
        IEnumerable<String> headerValues;
    
        if (request.Headers.TryGetValues("api-version", out headerValues) && headerValues.Count() == 1)
            versionAsString = headerValues.First();
        else
        {
            var accept = request.Headers.Accept.Where(a => a.Parameters.Count(p => p.Name == "version") > 0);
    
            if (accept.Any())
                versionAsString = accept.First().Parameters.Single(s => s.Name == "version").Value;
            else
            {
                accept = request.Headers.Accept.Where(a => Regex.IsMatch(a.MediaType, @"^application\/vnd\..*-v\d+\+.*$", RegexOptions.Singleline));
    
                if (accept.Any())
                    versionAsString = Regex.Match(accept.First().MediaType, @"^application\/vnd\..*-v(?<version>\d+)\+.*$", RegexOptions.Singleline).Groups["version"].Value;
            }
        }
    
        Int32 version;
    
        if (!String.IsNullOrEmpty(versionAsString) && Int32.TryParse(versionAsString, out version))
            return version;
    
        return null;
    }

    The Vendor MIME Type follows a specific pattern of "application/vnd.some.namespaced.resource+json". To version this, the convention is shaping up to look like this: application/vnd.some.namespaced.resource-v1+json

    The regular expressions in the GetVersionHeader method checks for this pattern and extracts the version if present.

    Run the project, open Fiddler, and compose a request like this:

    When you inspect the response, you should see the V2 version in the JSON tab. Now change the Accept to "application/vnd.webapiversioning.string-v2+xml" and execute the request. When you inspect the response you'll notice that it's still JSON and not XML! The reason is that MVC Web API doesn't parse Vendor MIME Types like it does the standard, generic MIME Types. Instead, Microsoft leaves it for you to create you own media type formatters to handle such cases.

    Add a new folder to the Core.Web project called "Extensions" and add the following class:

    namespace Core.Web.Extensions
    {
        public static class TypeExtensions
        {
            public static Type GetEnumerableType(this Type type)
            {
                if (IsIEnumerable(type))
                    return type.GetGenericArguments()[0];
                else
                {
                    foreach (var i in type.GetInterfaces())
                    {
                        if (IsIEnumerable(i))
                            return i.GetGenericArguments()[0];
                    }
                }
    
                return null;
            }
    
            private static Boolean IsIEnumerable(Type type)
            {
                return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
            }
        }
    }

    Next, add a new folder called "Http" to the Core.Web project and add the following classes:

    namespace Core.Web.Http
    {
        public class TypedJsonMediaTypeFormatter : JsonMediaTypeFormatter
        {
            private readonly Type _ResourceType;
    
            public TypedJsonMediaTypeFormatter(Type resourceType, MediaTypeHeaderValue mediaType)
            {
                _ResourceType = resourceType;
                SupportedMediaTypes.Clear();
                SupportedMediaTypes.Add(mediaType);
            }
    
            public override Boolean CanReadType(Type type)
            {
                return _ResourceType == type || _ResourceType == type.GetEnumerableType();
            }
    
            public override Boolean CanWriteType(Type type)
            {
                return _ResourceType == type || _ResourceType == type.GetEnumerableType();
            }
        }
    }
    namespace Core.Web.Http
    {
        public class TypedXmlMediaTypeFormatter : XmlMediaTypeFormatter
        {
            private readonly Type _ResourceType;
    
            public TypedXmlMediaTypeFormatter(Type resourceType, MediaTypeHeaderValue mediaType)
            {
                _ResourceType = resourceType;
                SupportedMediaTypes.Clear();
                SupportedMediaTypes.Add(mediaType);
            }
    
            public override Boolean CanReadType(Type type)
            {
                return _ResourceType == type || _ResourceType == type.GetEnumerableType();
            }
    
            public override Boolean CanWriteType(Type type)
            {
                return _ResourceType == type || _ResourceType == type.GetEnumerableType();
            }
        }
    }

    You will need to add a using for Core.Web.Extensions to each of these classes.

    These formatters, when registered with the application for a particular type, will format the response appropriately. Here is how you would perform that registration in Global.asax:

    namespace Web
    {
        public class WebApiApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
                GlobalConfiguration.Configure(WebApiConfig.Register);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
    
                GlobalConfiguration.Configuration.Formatters.Add(new TypedXmlMediaTypeFormatter(typeof(String), new MediaTypeHeaderValue("application/vnd.webapiversioning.string-v1+xml")));
                GlobalConfiguration.Configuration.Formatters.Add(new TypedJsonMediaTypeFormatter(typeof(String), new MediaTypeHeaderValue("application/vnd.webapiversioning.string-v1+json")));
                GlobalConfiguration.Configuration.Formatters.Add(new TypedXmlMediaTypeFormatter(typeof(String), new MediaTypeHeaderValue("application/vnd.webapiversioning.string-v2+xml")));
                GlobalConfiguration.Configuration.Formatters.Add(new TypedJsonMediaTypeFormatter(typeof(String), new MediaTypeHeaderValue("application/vnd.webapiversioning.string-v2+json")));
            }
        }
    }

    What we're saying with these registrations is that when a request is made for the type of resource specified in the Accept header and the response is of that type, then use the appropriate media type formatter to serialize the response.

    Now run the project, open Fiddler, and compose a request with an Accept header value "application/vnd.webapiversioning.string-v2+xml". You should now see an XML response.

    Again, I'm just focusing on the versioning mechanisms in this tutorial and not a typical, real-life scenario. Your Web API's will likely deal with resources that are more complex so your registrations would likely look something like this:

    GlobalConfiguration.Configuration.Formatters.Add(new TypedJsonMediaTypeFormatter(typeof(Product), new MediaTypeHeaderValue("application/vnd.mycompany.product-v1+json")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedJsonMediaTypeFormatter(typeof(Product_V2), new MediaTypeHeaderValue("application/vnd.mycompany.product-v2+json")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedXmlMediaTypeFormatter(typeof(Product), new MediaTypeHeaderValue("application/vnd.mycompany.product-v1+xml")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedXmlMediaTypeFormatter(typeof(Product_V2), new MediaTypeHeaderValue("application/vnd.mycompany.product-v2+xml")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedJsonMediaTypeFormatter(typeof(Customer), new MediaTypeHeaderValue("application/vnd.mycompany.customer-v1+json")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedJsonMediaTypeFormatter(typeof(Customer_V2), new MediaTypeHeaderValue("application/vnd.mycompany.customer-v2+json")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedXmlMediaTypeFormatter(typeof(Customer), new MediaTypeHeaderValue("application/vnd.mycompany.customer-v1+xml")));
    GlobalConfiguration.Configuration.Formatters.Add(new TypedXmlMediaTypeFormatter(typeof(Customer_V2), new MediaTypeHeaderValue("application/vnd.mycompany.customer-v2+xml")));
    

    I hope this tutorial gives you enough options to successfully version your Web API. If you have any questions or suggestions on how I can make this better, please leave a comment.

    You can download the source for this article here.

  2. Next Steps: Adding a Service Layer and Validation

    I've been using the Repository and UnitOfWork I created in my previous post in all of my projects with quite a lot of success. One of the things I noticed, though, is that there were occasions when I repeated the same LINQ query in several controller methods with the same business logic applied to the data. I also had cases where there was validation logic in my controllers that needed to be shared. That's no bueno. I set out to centralize that code but quickly realized that a lot more work was needed.

    I won't go through all of the project setup - you can see that in my previous post - but I will point out some changes I made in my updated code. I mentioned last time that it would be best to separate the ORM-specific repository and unit of work implementations into their own assembly so I did that in my updated Recreation project (see Core.EntityFramework). I also updated Entity Framework to version 6 and added asynchronous methods to the Repository and UnitOfWork interfaces and implementations.

    One of the cases where I noticed I was repeating the same query against the data across multiple controller methods was when I added the same dropdown list to several views. An example of this might be a view to create a Reservation and another view to edit a Reservation. Both controller methods might create SelectLists for facilities and guests and pass them to the view using the ViewBag. There would also likely be two methods for Edit and two for Create where these services would be used - one for the initial loading of the view and another for the HttpPost. The queries for facilities and guests would be the same in all of the controller methods so it makes sense to centralize that code somewhere. When I searched online for a pattern that fit this use case, the Service Layer pattern seemed to be the most appropriate:

    A Service Layer defines an application's boundary and its set of available operations from the perspective of interfacing client layers. It encapsulates the application's business logic, controlling transactions and coordinating responses in the implementation of its operations.

    The Service Layer classes for the Guest and Facility domain models look like this:

    namespace Recreation.Data.Services
    {
        public interface IFacilityService : IDisposable
        {
            Dictionary<Int32, String> GetSelections();
        }
    
        public class FacilityService : IFacilityService
        {
            private readonly IRepository<Facility> _FacilityRepository;
    
            public FacilityService(IRepository<Facility> facilityRepository)
            {
                _FacilityRepository = facilityRepository;
            }
    
            public Dictionary<Int32, String> GetSelections()
            {
                return (from q in _FacilityRepository.GetQueryable()
                        select new { q.Id, q.Name }).OrderBy(o => o.Name).ToDictionary(d => d.Id, d => d.Name);
            }
    
            public void Dispose()
            {
                if (_FacilityRepository != null)
                    _FacilityRepository.Dispose();
            }
        }
    }
    namespace Recreation.Data.Services
    {
        public interface IGuestService : IDisposable
        {
            Dictionary<Int32, String> GetSelections();
        }
    
        public class GuestService : IGuestService
        {
            private readonly IRepository<Guest> _GuestRepository;
    
            public GuestService(IRepository<Guest> facilityRepository)
            {
                _GuestRepository = facilityRepository;
            }
    
            public Dictionary<Int32, String> GetSelections()
            {
                return (from q in _GuestRepository.GetQueryable()
                        select new { q.Id, q.FirstName, q.LastName }).OrderBy(o => o.LastName).ToDictionary(d => d.Id, d => String.Format("{0}, {1}", d.LastName, d.FirstName));
            }
    
            public void Dispose()
            {
                if (_GuestRepository != null)
                    _GuestRepository.Dispose();
            }
        }
    }

    You will then need to register these services with Unity so that you can inject them into the controller:

    namespace Recreation.Web.App_Start
    {
        /// <summary>
        /// Specifies the Unity configuration for the main container.
        /// </summary>
        public class UnityConfig
        {
            #region Unity Container
    
            private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
            {
                var container = new UnityContainer();
                RegisterTypes(container);
                return container;
            });
    
            /// <summary>
            /// Gets the configured Unity container.
            /// </summary>
            public static IUnityContainer GetConfiguredContainer()
            {
                return container.Value;
            }
    
            #endregion
    
            /// <summary>Registers the type mappings with the Unity container.</summary>
            /// <param name="container">The unity container to configure.</param>
            /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
            /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
            public static void RegisterTypes(IUnityContainer container)
            {
                // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
                // container.LoadConfiguration();
                // TODO: Register your types here
    
                //Data Access
                container.RegisterType<IObjectContextAdapter, RecreationContext>(new PerRequestLifetimeManager());
                container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
                container.RegisterType<IUnitOfWork, UnitOfWork>();
    
                //Services
                container.RegisterType<IFacilityService, FacilityService>();
                container.RegisterType<IGuestService, GuestService>();
            }
        }
    }

    The ReservationController would then consume those services like this (I only included the Edit methods):

    namespace Recreation.Web.Controllers
    {
        public class ReservationController : Controller
        {
            private readonly IRepository<Reservation> _ReservationRepository;
            private readonly IFacilityService _FacilityService;
            private readonly IGuestService _GuestService;
            private readonly IUnitOfWork _UnitOfWork;
    
            public ReservationController(IRepository<Reservation> reservationRepository, IFacilityService facilityService, IGuestService guestService, IUnitOfWork unitOfWork)
            {
                _ReservationRepository = reservationRepository;
                _FacilityService = facilityService;
                _GuestService = guestService;
                _UnitOfWork = unitOfWork;
            }
    
            public ActionResult Index()
            {
                return View(_ReservationRepository.GetAll());
            }
    
            public ActionResult Edit(Int32 id = 0)
            {
                var reservation = _ReservationRepository.SingleOrDefault(r => r.Id == id);
    
                if (reservation == null)
                    return HttpNotFound();
    
                ViewBag.FacilityId = new SelectList(_FacilityService.GetSelections(), "Key", "Value", reservation.FacilityId);
                ViewBag.GuestId = new SelectList(_GuestService.GetSelections(), "Key", "Value", reservation.GuestId);
                
                return View(reservation);
            }
    
            [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Edit(Reservation reservation)
            {
                _ReservationRepository.Attach(reservation, EntityStatus.Modified);
    
                if (ModelState.IsValid)
                {
                    try
                    {
                        _UnitOfWork.SaveChanges();
                    }
                    catch (ConcurrencyException)
                    {
                        ModelState.AddModelError(String.Empty, "The record you attempted to edit was modified by another user after you got the original value. Your edit operation was canceled. If you still want to edit this record, save it again.");
                    }
                    catch (Exception)
                    {
                        ModelState.AddModelError(String.Empty, "Unable to save changes. Please try again.");
                    }
                }
    
                ViewBag.FacilityId = new SelectList(_FacilityService.GetSelections(), "Key", "Value", reservation.FacilityId);
                ViewBag.GuestId = new SelectList(_GuestService.GetSelections(), "Key", "Value", reservation.GuestId);
    
                return View(reservation);
            }
    
            protected override void Dispose(Boolean disposing)
            {
                if (disposing)
                {
                    _ReservationRepository.Dispose();
                    _FacilityService.Dispose();
                    _GuestService.Dispose();
                    _UnitOfWork.Dispose();
                }
    
                base.Dispose(disposing);
            }
        }
    }

    When the controller is created, Unity instantiates the Repository<Reservation> object specified in the controller's constructor. When it sees the Service Layer references, it instantiates the Repository<> objects in their respective constructors before instantiating the Service Layer objects.

    The Edit.cshtml view looks like this:

    @model Recreation.Data.Models.Reservation
    @{
        ViewBag.Title = "Edit Reservation";
    }
    <p>@Html.ActionLink("View Reservations", "Index")</p>
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>@ViewBag.Title</legend>
            @Html.HiddenFor(m => m.Id)
            @Html.HiddenFor(m => m.ConcurrencyToken)
            <ol>
                <li>
                    @Html.LabelFor(m => m.FacilityId)
                    @Html.DropDownList("FacilityId", "Select a Facility")
                    @Html.ValidationMessageFor(m => m.FacilityId)
                </li>
                <li>
                    @Html.LabelFor(m => m.GuestId)
                    @Html.DropDownList("GuestId", "Select a Guest")
                    @Html.ValidationMessageFor(m => m.GuestId)
                </li>
                <li>
                    @Html.LabelFor(m => m.StartDateTime)
                    @Html.TextBoxFor(m => m.StartDateTime)
                    @Html.ValidationMessageFor(m => m.StartDateTime)
                </li>
                <li>
                    @Html.LabelFor(m => m.EndDateTime)
                    @Html.TextBoxFor(m => m.EndDateTime)
                    @Html.ValidationMessageFor(m => m.EndDateTime)
                </li>
            </ol>
            <input type="submit" value="Submit" />
        </fieldset>
    }

    Validation

    Where to place validation logic - especially logic that isn't easily covered by MVC's HTML helper methods - is something that I've struggled with when it comes to MVC. Once I started down the path of creating a Service Layer, though, this became somewhat easier. I found this article on asp.net that explains placing validation logic in a Service Layer:

    So, application flow control logic belongs in a controller and data access logic belongs in a repository. In that case, where do you put your validation logic? One option is to place your validation logic in a service layer. A service layer is an additional layer in an ASP.NET MVC application that mediates communication between a controller and repository layer. The service layer contains business logic. In particular, it contains validation logic.

    Stephen Walther's approach is a good one but it didn't quite smell right to me - particularly with my Service Layer approach and my usage of the Inversion of Control (IoC) pattern using Unity. That led me to this question on Stack Overflow. The accepted answer by "Steven" was exactly what I needed. After some scrubbing and polishing, I ended up with what I think is an excellent way to do model and data validation in the Service Layer with MVC. I won't bore you with the details because "Steven" does a pretty good job of explaining everything.

    The ReservationValidator looks like this:

    namespace Recreation.Data.Validation
    {
        public class ReservationValidator : Validator<Reservation>
        {
            protected override IEnumerable<ValidationResult> Validate(Reservation entity)
            {
                if (entity.FacilityId <= 0)
                    yield return new ValidationResult("FacilityId", "You must select a Facility");
    
                if (entity.GuestId <= 0)
                    yield return new ValidationResult("GuestId", "You must select a Guest");
    
                if (entity.EndDateTime < entity.StartDateTime)
                    yield return new ValidationResult("EndDateTime", "The End Date/Time must be greater than the Start Date/Time");
    
                if ((entity.EndDateTime - entity.StartDateTime).TotalHours < 1)
                    yield return new ValidationResult("EndDateTime", "The End Date/Time must be at least one hour greater than the Start Date/Time");
            }
        }
    }

    And the ReservationService looks like this:

    namespace Recreation.Data.Services
    {
        public interface IReservationService : IDisposable
        {
            IEnumerable<Reservation> GetAll();
            Reservation GetById(Int32 id);
            void Update(Reservation reservation);
        }
    
        public class ReservationService : IReservationService
        {
            private readonly IRepository<Reservation> _ReservationRepository;
            private readonly IUnitOfWork _UnitOfWork;
            private readonly IValidationProvider _ValidationProvider;
    
            public ReservationService(IRepository<Reservation> reservationRepository, IUnitOfWork unitOfWork, IValidationProvider validationProvider)
            {
                _ReservationRepository = reservationRepository;
                _UnitOfWork = unitOfWork;
                _ValidationProvider = validationProvider;
            }
    
            public IEnumerable<Reservation> GetAll()
            {
                return _ReservationRepository.GetAll();
            }
    
            public Reservation GetById(Int32 id)
            {
                return _ReservationRepository.SingleOrDefault(r => r.Id == id);
            }
    
            public void Update(Reservation reservation)
            {
                _ValidationProvider.Validate(reservation);
                _ReservationRepository.Attach(reservation, EntityStatus.Modified);
                _UnitOfWork.SaveChanges();
            }
    
            public void Dispose()
            {
                if (_ReservationRepository != null)
                    _ReservationRepository.Dispose();
    
                if (_UnitOfWork != null)
                    _UnitOfWork.Dispose();
            }
        }
    }

    Registering the validators with Unity is pretty slick. The UnityConfig code now looks like this:

    namespace Recreation.Web.App_Start
    {
        /// <summary>
        /// Specifies the Unity configuration for the main container.
        /// </summary>
        public class UnityConfig
        {
            #region Unity Container
    
            private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
            {
                var container = new UnityContainer();
                RegisterTypes(container);
                return container;
            });
    
            /// <summary>
            /// Gets the configured Unity container.
            /// </summary>
            public static IUnityContainer GetConfiguredContainer()
            {
                return container.Value;
            }
    
            #endregion
    
            /// <summary>Registers the type mappings with the Unity container.</summary>
            /// <param name="container">The unity container to configure.</param>
            /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
            /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
            public static void RegisterTypes(IUnityContainer container)
            {
                // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
                // container.LoadConfiguration();
                // TODO: Register your types here
    
                //Data Access
                container.RegisterType<IObjectContextAdapter, RecreationContext>(new PerRequestLifetimeManager());
                container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
                container.RegisterType<IUnitOfWork, UnitOfWork>();
    
                //Services
                container.RegisterType<IFacilityService, FacilityService>();
                container.RegisterType<IGuestService, GuestService>();
                container.RegisterType<IReservationService, ReservationService>();
    
                //Validators
                container.RegisterInstance(typeof(IValidationProvider), new ValidationProvider(type => (IValidator)container.Resolve(typeof(Validator<>).MakeGenericType(type))));
                container.RegisterType(typeof(Validator<>), typeof(NullValidator<>));
                container.RegisterType<Validator<Reservation>, ReservationValidator>();
            }
        }
    }

    Using Func<Type, IValidator> as a Factory Pattern to instantiate the appropriate Validator based on the calling type is truly inspired. Kudos to "Steven" for coming up with that one!

    The ReservationController can now be updated to look like this:

    namespace Recreation.Web.Controllers
    {
        public class ReservationController : Controller
        {
            private readonly IReservationService _ReservationService;
            private readonly IFacilityService _FacilityService;
            private readonly IGuestService _GuestService;
    
            public ReservationController(IReservationService reservationService, IFacilityService facilityService, IGuestService guestService)
            {
                _ReservationService = reservationService;
                _FacilityService = facilityService;
                _GuestService = guestService;
            }
    
            public ActionResult Index()
            {
                return View(_ReservationService.GetAll());
            }
    
            public ActionResult Edit(Int32 id = 0)
            {
                var reservation = _ReservationService.GetById(id);
    
                if (reservation == null)
                    return HttpNotFound();
    
                ViewBag.FacilityId = new SelectList(_FacilityService.GetSelections(), "Key", "Value", reservation.FacilityId);
                ViewBag.GuestId = new SelectList(_GuestService.GetSelections(), "Key", "Value", reservation.GuestId);
    
                return View(reservation);
            }
    
            [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Edit(Reservation reservation)
            {
                try
                {
                    _ReservationService.Update(reservation);
                }
                catch (ValidationException vex)
                {
                    ModelState.AddErrors(vex);
                }
                catch (ConcurrencyException)
                {
                    ModelState.AddModelError(String.Empty, "The record you attempted to edit was modified by another user after you got the original value. Your edit operation was canceled. If you still want to edit this record, save it again.");
                }
                catch (Exception)
                {
                    ModelState.AddModelError(String.Empty, "Unable to save changes. Please try again.");
                }
    
                ViewBag.FacilityId = new SelectList(_FacilityService.GetSelections(), "Key", "Value", reservation.FacilityId);
                ViewBag.GuestId = new SelectList(_GuestService.GetSelections(), "Key", "Value", reservation.GuestId);
    
                return View(reservation);
            }
    
            protected override void Dispose(Boolean disposing)
            {
                if (disposing)
                {
                    _ReservationService.Dispose();
                    _FacilityService.Dispose();
                    _GuestService.Dispose();
                }
    
                base.Dispose(disposing);
            }
        }
    }

    These changes make the controller much more streamlined. I hope you can get some good use out of this. I've been using combinations of the Repository, UnitOfWork, and Service Layer patterns for the past several months and my projects have resulted in easier-to-read code and better maintainability. You can grab the code for the new Recreation project here.

  3. Simple CAPTCHA for MVC

    I recently overhauled this blog so that I could convert everything to MVC 5 and Entity Framework 6. While I was at it, I removed the ASP.NET Membership system and simplified the comment process. I had two reasons for doing this: 1) the new Membership system blows and 2) the Russians. You see, I was getting between 10 and 50 new member notifications every day - the vast majority of which were SPAM bots using ".ru" email addresses. It became clear that I'd have to implement something to counter the spammers.

    I searched for half a day looking for a CAPTCHA that looked good, was easy to implement, and was MVC-friendly. Surprisingly, I didn't really find much. I looked at reCAPTCHA but didn't really like its aesthetics or its implementation. There are several blog posts, CodeProject articles, and NuGet packages for CAPTCHA but most of their implementations rely on session variables to transport the CAPTCHA value - something I wanted to avoid. Writing my own ended up being pretty simple and, so far, very effective.

    The interface for the CAPTCHA is pretty simple. There's a challenge (the characters on the image that the user needs to type into a form field) and a response (the user's input).

    public interface ICaptcha
    {
        String Challenge { get; set; }
        String Response { get; set; }
    }

    For the implementation, I used the Random class to select from a string of characters and then used UrlTokenEncode to encode the challenge. I used UrlTokenEncode because I'll be creating an image request to a MVC action and pass the encoded challenge in the URL. UrlTokenEncode does a nice job of munging the characters and makes it safe for use in the URL. Also note that the characters I use do not include the letters "I" or "O" nor the numbers "1" or "0" so that there's no confusion among them when the characters are rendered in the image.

    public class Captcha : ICaptcha
    {
        private const Int32 TEXT_LENGTH = 5;
        private const String TEXT_CHARS = "ACDEFGHJKLNPQRTUVXYZ2346789";
        private Random _Random;
    
        public Captcha()
        {
            _Random = new Random();
            Challenge = HttpServerUtility.UrlTokenEncode(System.Text.UTF8Encoding.ASCII.GetBytes(GenerateChallenge()));
        }
    
        public String Challenge { get; set; }
    
        [CaptchaValidator]
        public String Response { get; set; }
    
        private String GenerateChallenge()
        {
            StringBuilder stringBuilder = new StringBuilder(TEXT_LENGTH);
    
            for (Int32 i = 0; i < TEXT_LENGTH; i++)
                stringBuilder.Append(TEXT_CHARS.Substring(_Random.Next(TEXT_CHARS.Length), 1));
    
            return stringBuilder.ToString();
        }
    }
    

    The user's response is validated using a custom ValidationAttribute. Although the characters are rendered as upper-case characters, case is ignored when validating the user's input.

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    public class CaptchaValidatorAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(Object value, ValidationContext validationContext)
        {
            if (validationContext.ObjectType.Name != "Captcha")
                return new ValidationResult("This attribute is being used incorrectly");
    
            if (value == null)
                return new ValidationResult("You must enter the CAPTCHA characters in the image");
    
            if (0 != String.Compare(UTF8Encoding.ASCII.GetString(HttpServerUtility.UrlTokenDecode(((Captcha)validationContext.ObjectInstance).Challenge)), value.ToString(), true))
                return new ValidationResult("CAPTCHA is not valid");
    
            return ValidationResult.Success;
        }
    }
    

    To help out on the MVC side of things, I created a HtmlHelper extension to handle the image tag and the hidden field to pass the encoded challenge upon HTTP posts.

    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString Captcha<TModel, TProperty>(this System.Web.Mvc.HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, String action, String controller) where TProperty : ICaptcha
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
            String htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            String propertyName = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last(); 
    
            TModel model = (TModel)html.ViewContext.ViewData.ModelMetadata.Model;
            TProperty captcha = expression.Compile().Invoke(model);
    
            UrlHelper urlHelper = new UrlHelper(html.ViewContext.RequestContext);
            String url = urlHelper.Action(action, controller, new { id = captcha.Challenge });
    
            return new MvcHtmlString(String.Format("<img src=\"{0}\" alt=\"CAPTCHA\" /><input id=\"{1}_Challenge\" name=\"{1}.Challenge\" type=\"hidden\" value=\"{2}\" />", url, propertyName, captcha.Challenge));
        }
    }

    The HtmlHelper accepts the model's Captcha property via an expression as well as values for the action and controller of the MVC controller method that's called to generate the image. Here's a sample of what that controller might look like:

    public class CaptchaController : Controller
    {
        public FileContentResult Image(String id)
        {
            return File(new CaptchaImage(id).ImageBytes, "image/jpeg");
        }
    }

    The CaptchaImage class accepts the encoded challenge, decodes it, and renders it onto an image. To make it difficult for OCR readers, I use random fonts, colors, transforms, and background noise.

    public class CaptchaImage
    {
        private readonly String _Text;
        private readonly Random _Random;
        private readonly Int32 _Height;
        private readonly Int32 _Width;
        private readonly String[] _RandomFontFamily = { "arial", "arial black", "comic sans ms", "courier new", "lucida console", "lucida sans unicode", "microsoft sans serif", "tahoma", "times new roman", "trebuchet ms", "verdana" };
        private readonly Color[] _RandomColor = { Color.Red, Color.Green, Color.Blue, Color.Black, Color.Purple, Color.Orange };
    
        public CaptchaImage(String text, Int32 height = 60, Int32 width = 300)
        {
            _Random = new Random();
            _Text = UTF8Encoding.ASCII.GetString(HttpServerUtility.UrlTokenDecode(text));
            _Height = height;
            _Width = width;
        }
    
        public Byte[] ImageBytes { get { return GenerateImageBytes(); } }
    
        private Byte[] GenerateImageBytes()
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (Bitmap bitmap = new Bitmap(_Width, _Height, PixelFormat.Format24bppRgb))
                {
                    using (Graphics graphics = Graphics.FromImage(bitmap))
                    {
                        graphics.SmoothingMode = SmoothingMode.AntiAlias;
                        graphics.Clear(Color.White);
    
                        Int32 charOffset = 0;
                        Double charWidth = _Width / _Text.Length;
                        Rectangle charRectangle;
    
                        Rectangle rectangle = new Rectangle(new Point(0, 0), bitmap.Size);
                        Int32 density = 18;
                        Int32 size = 40;
    
                        using (SolidBrush brush = new SolidBrush(Color.Gray))
                        {
                            Int32 max = Convert.ToInt32(Math.Max(rectangle.Width, rectangle.Height) / size);
    
                            for (Int32 i = 0; i <= Convert.ToInt32((rectangle.Width * rectangle.Height) / density); i++)
                                graphics.FillEllipse(brush, _Random.Next(rectangle.Width), _Random.Next(rectangle.Height), _Random.Next(max), _Random.Next(max));
                        }
    
                        Int32 length = 5;
                        PointF[] pointF = new PointF[length + 1];
                        using (Pen p = new Pen(GetRandomColor(), Convert.ToSingle(_Height / 27.7777)))
                        {
                            for (Int32 i = 0; i <= length; i++)
                                pointF[i] = RandomPoint(rectangle);
    
                            graphics.DrawCurve(p, pointF, 1.75F);
                        }
    
                        foreach (Char character in _Text)
                        {
                            using (Font font = new Font(_RandomFontFamily[_Random.Next(0, _RandomFontFamily.Length)], Convert.ToInt32(_Height * 0.85), FontStyle.Bold))
                            {
                                using (Brush fontBrush = new SolidBrush(GetRandomColor()))
                                {
                                    charRectangle = new Rectangle(Convert.ToInt32(charOffset * charWidth), 0, Convert.ToInt32(charWidth), _Height);
    
                                    StringFormat stringFormat = new StringFormat();
                                    stringFormat.Alignment = StringAlignment.Near;
                                    stringFormat.LineAlignment = StringAlignment.Near;
    
                                    GraphicsPath graphicsPath = new GraphicsPath();
                                    graphicsPath.AddString(character.ToString(), font.FontFamily, (Int32)font.Style, font.Size, charRectangle, stringFormat);
    
                                    Single warpDivisor = 5F;
                                    Single rangeModifier = 1.3F;
                                    RectangleF rectangleF = new RectangleF(Convert.ToSingle(charRectangle.Left), 0, Convert.ToSingle(charRectangle.Width), charRectangle.Height);
                                    Int32 hRange = Convert.ToInt32(charRectangle.Height / warpDivisor);
                                    Int32 wRange = Convert.ToInt32(charRectangle.Width / warpDivisor);
                                    Int32 left = charRectangle.Left - Convert.ToInt32(wRange * rangeModifier);
                                    Int32 top = charRectangle.Top - Convert.ToInt32(hRange * rangeModifier);
                                    Int32 width = charRectangle.Left + charRectangle.Width + Convert.ToInt32(wRange * rangeModifier);
                                    Int32 height = charRectangle.Top + charRectangle.Height + Convert.ToInt32(hRange * rangeModifier);
    
                                    if (left < 0)
                                        left = 0;
    
                                    if (top < 0)
                                        top = 0;
    
                                    if (width > _Width)
                                        width = _Width;
    
                                    if (height > _Height)
                                        height = _Height;
    
                                    PointF leftTop = RandomPoint(left, left + wRange, top, top + hRange);
                                    PointF rightTop = RandomPoint(width - wRange, width, top, top + hRange);
                                    PointF leftBottom = RandomPoint(left, left + wRange, height - hRange, height);
                                    PointF rightBottom = RandomPoint(width - wRange, width, height - hRange, height);
                                    PointF[] points = new PointF[] { leftTop, rightTop, leftBottom, rightBottom };
    
                                    Matrix matrix = new Matrix();
                                    matrix.Translate(0, 0);
    
                                    graphicsPath.Warp(points, rectangleF, matrix, WarpMode.Perspective, 0);
    
                                    graphics.FillPath(fontBrush, graphicsPath);
    
                                    charOffset += 1;
                                }
                            }
                        }
    
                        bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
    
                        return memoryStream.ToArray();
                    }
                }
            }
        }
    
        private Color GetRandomColor()
        {
            return _RandomColor[_Random.Next(0, _RandomColor.Length)];
        }
    
        private PointF RandomPoint(Int32 xMin, Int32 xMax, Int32 yMin, Int32 yMax)
        {
            return new PointF(_Random.Next(xMin, xMax), _Random.Next(yMin, yMax));
        }
    
        private PointF RandomPoint(Rectangle rectangle)
        {
            return RandomPoint(rectangle.Left, rectangle.Width, rectangle.Top, rectangle.Bottom);
        }
    }

    Here is a sample MVC project. Let me know what you think!

  4. Getting Started: MVC 4, Entity Framework 5 Code First, and Unity

    After several hours of banging my head against the wall, I finally have a good, working prototype for using Entity Framework 5 Code First in a MVC application with the Unity Inversion of Control (IoC) container for dependency injection. (Say that 3 times fast!) I'm using an IoC container for a couple of reasons. For one, it'll allow me to (somewhat) easily swap out components if I want. For example, if I want to use nHibernate for data access instead of Entity Framework, all I'll need to do is change to what the context, IRepository, and IUnitOfWork interfaces resolve. All of the code I write in the Controllers or elsewhere can stay the same. Another reason I want to use an IoC is because it'll make my components (somewhat) easy to mock (or fake) to supply a way to perform integration tests without having to use the actual services (e.g. I can create an object graph in code and use that in place of making calls to the database). Also, I'll be using the IoC to perform dependency injection (DI) so I'll "inject" my services into the controllers' contructors as well as the contructors of any other objects that depend on my services. This provides an easy way to create services and use them without having to write the code to instantiate them.

    Let's Begin

    First, let's create a MVC Web application. I'm creating a very simple application for an imaginary Parks & Recreation center so I'll call it "Recreation."

    MVC project creation

    For the type of MVC Web application, I'm going to go with the Basic template. I'm also going to create a unit test project but I'll save the unit tests for another post.

    Basic MVC application

    Once the project is created, add a new controller and name it "HomeController."

    Home Controller

    When the HomeController.cs file opens, right-click in the Index() method and select "Add View..."

    Now run the application (F5) to make sure everything compiles and runs.

    Create a Model/Data Access Layer

    Next, we're going to add a separate class library for our entities/models. Add a new project to the solution and name it "Data."

    Data class library

    Once the project is created, add the assembly references for "System.ComponentModel.DataAnnotations." Then use the NuGet Package Manager to add Entity Framework.

    Entity Framework

    Next create folders named "Context" and "Models" and add the following classes:

    Data Project set-up

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace Data.Models
    {
        public class Facility
        {
            [Key]
            public Int32 Id { get; set; }
    
            [StringLength(100)]
            public String Name { get; set; }
            public Int32 SquareFeet { get; set; }
    
            [Timestamp]
            public Byte[] ConcurrencyToken { get; set; }
    
            public virtual ICollection<Reservation> Reservations { get; set; }
        }
    }
        
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace Data.Models
    {
        public class Guest
        {
            [Key]
            public Int32 Id { get; set; }
    
            [StringLength(100)]
            public String FirstName { get; set; }
            [StringLength(100)]
            public String LastName { get; set; }
    
            [Timestamp]
            public Byte[] ConcurrencyToken { get; set; }
    
            public virtual ICollection<Reservation> Reservations { get; set; }
        }
    }
        
    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace Data.Models
    {
        public class Reservation
        {
            [Key]
            public Int32 Id { get; set; }
            public DateTime StartDateTime { get; set; }
            public DateTime EndDateTime { get; set; }
    
            [Display(Name = "Facility")]
            public Int32 FacilityId { get; set; }
    
            [Display(Name = "Guest")]
            public Int32 GuestId { get; set; }
    
            [Timestamp]
            public Byte[] ConcurrencyToken { get; set; }
    
            public virtual Facility Facility { get; set; }
            public virtual Guest Guest { get; set; }
        }
    }
        
    using Data.Models;
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration.Conventions;
    
    namespace Data.Context
    {
        public class RecreationContext : DbContext
        {
            public RecreationContext()
                : base("name=DefaultConnection")
            {
            }
    
            public DbSet<Facility> Facilities { get; set; }
            public DbSet<Guest> Guests { get; set; }
            public DbSet<Reservation> Reservations { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
                modelBuilder.Entity<Facility>().Property(p => p.ConcurrencyToken).IsConcurrencyToken();
                modelBuilder.Entity<Guest>().Property(p => p.ConcurrencyToken).IsConcurrencyToken();
                modelBuilder.Entity<Reservation>().Property(p => p.ConcurrencyToken).IsConcurrencyToken();
            }
        }
    }
        

    The "RecreationContext" class is like our gateway to the database. We're first going to use it to create the database. The three DbSet properties establish our tables available through the context. The "OnModelCreating" method allows us to set additional characteristics or properties on the tables as well as do things like change the way columns are named or create specific types of relationships between our tables. Here, we're setting up the "ConcurrencyToken" properties in our models to render as timestamp columns in the database. I'm doing this so that we can handle optimistic concurrency (when two or more people retrieve the same record and then attempt to save and overwrite one of the other person's changes).

    To enable Entity Framework Code First, open the Package Manager Console, set the default project to the "Data" project, and type the following:

    Package Manager Console - Enable Migrations

    This will add a new directory to your project, "Migrations," and a new class, "Configuration." The configuration class has a method that will help us seed the new database with some initial values. Replace the Seed method with this:

    protected override void Seed(Data.Context.RecreationContext context)
    {
        var facilities = new List<Facility>()
        {
            new Facility(){
                Name = "West Pavillion",
                SquareFeet = 12020,
                Reservations = new List<Reservation>()
            },
            new Facility(){
                Name = "East Pavillion",
                SquareFeet = 14500,
                Reservations = new List<Reservation>()
            },
            new Facility(){
                Name = "Bounce House",
                SquareFeet = 3000,
                Reservations = new List<Reservation>()
            },
            new Facility(){
                Name = "Botanical Garden",
                SquareFeet = 23123,
                Reservations = new List<Reservation>()
            }
        };
    
        facilities.ForEach(e => context.Facilities.AddOrUpdate(i => i.Name, e));
        context.SaveChanges();
    
        var guests = new List<Guest>()
        {
            new Guest(){
                FirstName = "Adam",
                LastName = "Jones",
                Reservations = new List<Reservation>()
            },
            new Guest(){
                FirstName = "Tiffany",
                LastName = "Bresnev",
                Reservations = new List<Reservation>()
            },
            new Guest(){
                FirstName = "Jackson",
                LastName = "Ackton",
                Reservations = new List<Reservation>()
            }
        };
    
        guests.ForEach(e => context.Guests.AddOrUpdate(i => i.LastName, e));
        context.SaveChanges();
    
        var reservations = new List<Reservation>()
        {
            new Reservation(){
                StartDateTime = new DateTime(2013, 1, 1),
                EndDateTime = new DateTime(2013, 1, 1),
                FacilityId = facilities.Single(p => p.Name == "West Pavillion").Id,
                GuestId = guests.Single(p => p.LastName == "Jones").Id
            },
            new Reservation(){
                StartDateTime = new DateTime(2013, 2, 1),
                EndDateTime = new DateTime(2013, 2, 1),
                FacilityId = facilities.Single(p => p.Name == "Bounce House").Id,
                GuestId = guests.Single(p => p.LastName == "Bresnev").Id
            },new Reservation(){
                StartDateTime = new DateTime(2013, 3, 1),
                EndDateTime = new DateTime(2013, 3, 1),
                FacilityId = facilities.Single(p => p.Name == "Botanical Garden").Id,
                GuestId = guests.Single(p => p.LastName == "Ackton").Id
            }
        };
    
        reservations.ForEach(e => context.Reservations.AddOrUpdate(i => new { i.StartDateTime, i.EndDateTime, i.FacilityId, i.GuestId }, e));
        context.SaveChanges();
    }
        

    When we tell Entity Framework to create the database, the Package Manager Console will look at our start-up project (the MVC project, in this case) and look for the connection string we specified in the RecreationContext class ("DefaultConnection"). I'm going to leave the connection string as the default and create a local database file in the App_Data folder. If you want the database to be created elsewhere, just update the connection string in the Web.config. Next, open the Package Manager Console and type the following:

    Package Manager Console - Initial Create

    This will create a class named "InitialCreate" that has the code necessary for Entity Framework to create the tables in our database. To create the database and generate the tables, type the following in the Package Manager Console:

    Package Manager Console - update-database

    If you open the Server Explorer -> DefaultConnection -> Tables, right-click on the Guest table, and select "Show Table Data," you should see the following:

    Server Explorer

    Let's make sure it works from our MVC application. Replace your HomeController with this:

    using Data.Context;
    using System.Linq;
    using System.Web.Mvc;
    
    namespace Recreation.Controllers
    {
        public class HomeController : Controller
        {
            private RecreationContext db = new RecreationContext();
    
            public ActionResult Index()
            {
                return View(db.Guests.ToList());
            }
    
            protected override void Dispose(bool disposing)
            {
                db.Dispose();
                base.Dispose(disposing);
            }
        }
    }
        

    Then modify your Views -> Home -> Index.cshtml file to look like this:

    @model List<Data.Models.Guest>
    @{
        ViewBag.Title = "Home";
    }
    
    <h2>@ViewBag.Title</h2>
    <ul>
        @foreach (var m in Model)
        {
            <li>@m.FirstName @m.LastName</li>
        }
    </ul>
        

    Run the application (F5) and you should see the three names we seeded to the database when it was created.

    Using the Unity IoC Container to Inject Dependencies in Your Controller

    First, install the Unity bootstrapper for ASP.NET MVC.

    NuGet Unity Bootstrapper

    This will also add the Unity NuGet package. The bootstrapper adds the necessary files in the MVC project's App_Start directory to initialize Unity and set the dependencies (the things you want to inject into other classes or methods). If you look in App_Start, you'll see two new files: UnityConfig.cs and UnityMvcActivator.cs. UnityMvcActivator uses WebActivatorEx to call the class's Start() method during application start. Of particular interest in the Start() method are the following lines:

    // TODO: Uncomment if you want to use PerRequestLifetimeManager
    // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
        

    Unity has what's called "lifetime managers" that manages how long any given object stays instantiated (alive). The The PerRequestLifetimeManager calls Dispose() on any object that makes use of the manager at the end of the HTTP request. We want to do this for our ObjectContext (RecreationContext) object so that it doesn't stay alive on the server, available for other requests. Make sure you uncomment the line so that we can safely dispose of any resources that implement IDisposable.

    The reason for my aforementiond head-banging was that I installed "Unity" and "Unity.MVC4" NuGet packages instead of the "Unity bootstrapper for ASP.NET MVC" package. The PerRequestLifetimeManager and UnityPerRequestHttpModule are only available in the bootstrapper package. I attempted to build several per-request lifetime managers but could never get them to call Dispose() on my managed services. It was ultimately the HttpModule that I was missing.

    Using the Inversion of Control, Repository, and Unit Of Work Patterns

    The Inversion of Control (IoC) pattern is all about resolving one type to another type. This resolution could be based on inheritance but most often you'll see it based on an interface. With this pattern, you develop against an interface and let the IoC container resolve it to a concrete implementation of that interface. You could have any number of implementations, it's up to the IoC container to create one for you. One of the ways it can do this is through Dependency Injection (DI). What you have is a consumer component (e.g. a MVC controller) that declares a dependency (or multiple dependencies) that it needs to get its job done. (Most commonly, you'll see this done through the constructor but some IoC frameworks allow you to inject through properties.) The IoC container creates an instance of a class that implements that given interface at runtime and "injects" it into that component. This pattern is somewhat like the Factory method pattern except that IoC relies on an external framework to operate (e.g. Unity, Windsor, Ninject, StructureMap). So IoC is really more of an architectural pattern as opposed to a design pattern.

    What we want now is an interface we can program against to get data from the Entity Framework ObjectContext (RecreationContext) we set up earlier. The interface should be generic enough that we can swap it out for another data access framework if we want but still robust enough to give us what we need to get things done in our controllers. The Repository pattern is ideal for this situation:

    A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes.

    So the repository is responsible for persisting our objects in memory but what about when it comes time to save changes to the collection(s) back to the database? That's where the Unit of Work pattern comes into play:

    A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.

    Perfect!

    So that we can reuse our Repository and UnitOfWork classes, lets create a separate class library and call it something like "Core." Note that I'm placing it in the Projects directory and not the Recreation directory. That way I can easily reference the assembly when creating other projects. A "core" assembly is a great place to store commonly used code like extension methods, helper methods, and anything else you may want to use from project-to-project. (Ideally, you would place the IRepository and IUnitOfWork interfaces - along with their dependencies - in a "core" assembly and then create another assembly with an ORM-specific implementation but I'm going to combine them at this time for the sake of simplicity.)

    Core Class Library

    After you create the class library, install Entity Framework from the NuGet Package Manager then add these interfaces, classes, and enum:

    namespace Core
    {
        public enum EntityStatus : int
        {
            Added,
            Deleted,
            Detached,
            Modified,
            Unchanged
        }
    }
        
    using System;
    using System.Runtime.Serialization;
    
    namespace Core
    {
        public class ConcurrencyException : SystemException
        {
            public ConcurrencyException()
                : base()
            {
            }
    
            public ConcurrencyException(String message)
                : base(message)
            {
            }
    
            public ConcurrencyException(String message, Exception innerException)
                : base(message, innerException)
            {
            }
    
            public ConcurrencyException(SerializationInfo info, StreamingContext context)
                : base(info, context)
            {
            }
        }
    }
        
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace Core
    {
        public interface IRepository<T> : IDisposable where T : class
        {
            IQueryable<T> GetQueryable();
            IEnumerable<T> GetAll();
            IEnumerable<T> Find(Expression<Func<T, Boolean>> where);
            T Single(Expression<Func<T, Boolean>> where);
            T First(Expression<Func<T, Boolean>> where);
            void Delete(T entity);
            void Add(T entity);
            void Attach(T entity);
            void Attach(T entity, EntityStatus status);
        }
    }
        
    using System;
    
    namespace Core
    {
        public interface IUnitOfWork : IDisposable
        {
            void SaveChanges();
        }
    }
        
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Entity.Infrastructure;
    using System.Data.Objects;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace Core
    {
        public class Repository<T> : IRepository<T> where T : class
        {
            private readonly IObjectContextAdapter _ObjectContextAdapter;
            IObjectSet<T> _ObjectSet;
    
            public Repository(IObjectContextAdapter objectContextAdapter)
            {
                _ObjectContextAdapter = objectContextAdapter;
                _ObjectSet = objectContextAdapter.ObjectContext.CreateObjectSet<T>();
            }
    
            public IQueryable<T> GetQueryable()
            {
                return _ObjectSet;
            }
    
            public IEnumerable<T> GetAll()
            {
                return _ObjectSet.ToList();
            }
    
            public IEnumerable<T> Find(Expression<Func<T, Boolean>> where)
            {
                return _ObjectSet.Where(where);
            }
    
            public T Single(Expression<Func<T, Boolean>> where)
            {
                return _ObjectSet.Single(where);
            }
    
            public T First(Expression<Func<T, Boolean>> where)
            {
                return _ObjectSet.First(where);
            }
    
            public void Delete(T entity)
            {
                _ObjectSet.DeleteObject(entity);
            }
    
            public void Add(T entity)
            {
                _ObjectSet.AddObject(entity);
            }
    
            public void Attach(T entity)
            {
                Attach(entity, EntityStatus.Unchanged);
            }
    
            public void Attach(T entity, EntityStatus status)
            {
                _ObjectSet.Attach(entity);
                _ObjectContextAdapter.ObjectContext.ObjectStateManager.ChangeObjectState(entity, GetEntityState(status));
            }
    
            public void Dispose()
            {
                if (_ObjectContextAdapter != null)
                    _ObjectContextAdapter.ObjectContext.Dispose();
    
                GC.SuppressFinalize(this);
            }
    
            private EntityState GetEntityState(EntityStatus status)
            {
                switch (status)
                {
                    case EntityStatus.Added:
                        return EntityState.Added;
                    case EntityStatus.Deleted:
                        return EntityState.Deleted;
                    case EntityStatus.Detached:
                        return EntityState.Detached;
                    case EntityStatus.Modified:
                        return EntityState.Modified;
                    default:
                        return EntityState.Unchanged;
                }
            }
        }
    }
        
    using System;
    using System.Data;
    using System.Data.Entity.Infrastructure;
    
    namespace Core
    {
        public class UnitOfWork : IUnitOfWork
        {
            private readonly IObjectContextAdapter _ObjectContextAdapter;
    
            public UnitOfWork(IObjectContextAdapter objectContextAdapter)
            {
                _ObjectContextAdapter = objectContextAdapter;
            }
    
            public void SaveChanges()
            {
                try
                {
                    _ObjectContextAdapter.ObjectContext.SaveChanges();
                }
                catch (OptimisticConcurrencyException oce)
                {
                    throw new ConcurrencyException(oce.Message, oce.InnerException);
                }
                catch (DataException)
                {
                    throw;
                }
            }
    
            public void Dispose()
            {
                if (_ObjectContextAdapter != null)
                    _ObjectContextAdapter.ObjectContext.Dispose();
    
                GC.SuppressFinalize(this);
            }
        }
    }
        

    To implement the repository and unit of work into our MVC application, update the UnityConfig.cs file as follows:

    using Core;
    using Data.Context;
    using Microsoft.Practices.Unity;
    using System;
    using System.Data.Entity.Infrastructure;
    
    namespace Recreation.App_Start
    {
        /// <summary>
        /// Specifies the Unity configuration for the main container.
        /// </summary>
        public class UnityConfig
        {
            #region Unity Container
            private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
            {
                var container = new UnityContainer();
                RegisterTypes(container);
                return container;
            });
    
            /// <summary>
            /// Gets the configured Unity container.
            /// </summary>
            public static IUnityContainer GetConfiguredContainer()
            {
                return container.Value;
            }
            #endregion
    
            /// <summary>Registers the type mappings with the Unity container.</summary>
            /// <param name="container">The unity container to configure.</param>
            /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
            /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
            public static void RegisterTypes(IUnityContainer container)
            {
                // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
                // container.LoadConfiguration();
    
                // TODO: Register your types here
                container.RegisterType<IObjectContextAdapter, RecreationContext>(new PerRequestLifetimeManager());
                container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
                container.RegisterType<IUnitOfWork, UnitOfWork>();
            }
        }
    }
        

    What we're doing here is registering the interfaces and associating them with a concrete type in the RegisterTypes() method. Throughout the MVC application, we'll program against the interface but at runtime, Unity will inject a concrete instance of the interface.

    In the above code, the RecreationContext is instantiated per-request thanks to the PerRequestLifetimeManager. Here's the cool part: both Repository and UnitOfWork have constructors that accept IObjectContextAdapter. When the concrete implementations are instantiated, Unity injects the RecreationContext into them and then they get injected into the controller (see below). Both the Repository and the UnitOfWork then share the same context per request so that anything that happens in the Repository gets reflected in the UnitOfWork. How freaking cool is that?!

    Now we can update our HomeController to look like this:

    using Core;
    using Data.Models;
    using System.Web.Mvc;
    
    namespace Recreation.Controllers
    {
        public class HomeController : Controller
        {
            IRepository<Guest> _GuestRepository;
    
            public HomeController(IRepository<Guest> guestRepository)
            {
                _GuestRepository = guestRepository;
            }
    
            public ActionResult Index()
            {
                return View(_GuestRepository.GetAll());
            }
    
            protected override void Dispose(bool disposing)
            {
                _GuestRepository.Dispose();
                base.Dispose(disposing);
            }
        }
    }
        

    Now run the application (F5) and verify that the save values from the database are displayed in the view.

    When the controller is created, Unity inspects its constructor and compares the types in the signature with the registered types in its container. In this case, it found a generic IRepository<> interface and passed in an instance of the Repository<> class. By making the IRepository interface and Repository concrete implementation generic, we can create repositories for any number of Entity objects. You can inject as many items into a constructor as you want, too. Just add them to the constructor's method signature [e.g. public HomeController(IRepository<Guest> guestRepository, IRepository<Facility> facilityRepository, IRepository<Reservation> reservationRepository) and so on...]

    When you make changes through the repository, you're actually making changes to the Entities in the underlying ObjectContext. When it comes time to commit those changes back to the database, the Unit of Work we created earlier has that responsibility. Update your HomeController to this:

    using Core;
    using Data.Models;
    using System;
    using System.Web.Mvc;
    
    namespace Recreation.Controllers
    {
        public class HomeController : Controller
        {
            IRepository<Guest> _GuestRepository;
            IUnitOfWork _UnitOfWork;
    
            public HomeController(IRepository<Guest> guestRepository, IUnitOfWork unitOfWork)
            {
                _GuestRepository = guestRepository;
                _UnitOfWork = unitOfWork;
            }
    
            public ActionResult Index()
            {
                return View(_GuestRepository.GetAll());
            }
    
            public ActionResult Edit()
            {
                return View(_GuestRepository.First(g => g.LastName == "Bresnev"));
            }
    
            [HttpPost]
            public ActionResult Edit(Guest guest)
            {
                _GuestRepository.Attach(guest, EntityStatus.Modified);
    
                if (ModelState.IsValid)
                {
                    try
                    {
                        _UnitOfWork.SaveChanges();
                    }
                    catch (ConcurrencyException)
                    {
                        ModelState.AddModelError(String.Empty, "The record you attempted to edit was modified by another user after you got the original value. Your edit operation was canceled. If you still want to edit this record, save it again.");
                    }
                    catch (Exception)
                    {
                        ModelState.AddModelError(String.Empty, "Unable to save changes. Please try again.");
                    }
                }
    
                return View(guest);
            }
    
            protected override void Dispose(bool disposing)
            {
                _GuestRepository.Dispose();
                _UnitOfWork.Dispose();
                base.Dispose(disposing);
            }
        }
    }
        

    Right-click within the Edit() method and add a View. Change the Edit.cshtml view to look like this:

    @model Data.Models.Guest
    @{
        ViewBag.Title = "Edit";
    }
    
    <h2>@ViewBag.Title</h2>
    <ul>
        <li>@Model.FirstName @Model.LastName</li>
    </ul>
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
    
        @Html.TextBoxFor(m => m.FirstName);
        
        @Html.HiddenFor(m => m.Id)
        @Html.HiddenFor(m => m.LastName)
        @Html.HiddenFor(m => m.ConcurrencyToken)
        <input type="submit" value="Change First Name" />
    }
        

    I realize this is a pretty lame example but I just wanted to get the idea across.

    The reason for creating my own ConcurrencyException and managing my own Entity state/status is that I didn't want to create any dependencies on Entity Framework in the interfaces. I'm not sure about other ORM's but I can imagine that there are ways on others to manage concurrency exceptions or the status change of an object. The point, though, is to make an interface that's as neutral as possible to a concrete implementation so that you can change the concrete implementation without having to change the interface and the code depending on that interface.

    Please let me know if you have any suggestions on how to make this better!

    You can get the code here.

  5. Displaying an enum in an MVC DropDown with custom text using the DisplayAttribute

    I'm working on a project that has several classes with enum-backed properties. When rendering those properties in an MVC view, I wanted to display them as a dropdown list. Here's an extension method I created that does that:

    public static IHtmlString DropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
        Type enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;
        IEnumerable<Object> enumValues = Enum.GetValues(enumType).Cast<Object>();
        IEnumerable<SelectListItem> items = from enumValue in enumValues
                                            select new SelectListItem
                                            {
                                                Text = enumValue.ToString(),
                                                Value = ((Int32)enumValue).ToString(),
                                                Selected = enumValue.Equals(metadata.Model)
                                            };
        return html.DropDownListFor(expression, items, String.Empty, null);
    }
        

    This extension takes the enum and displays each enumerator exactly as it's written. That seemed to work pretty well for the simple enums I had in my project. Then I created and enum that looked like this:

    public enum DeliveryMethod
    {
        CompetitiveSealedProposal,
        ConstructionManagerRisk,
        ConstructionManagerAgent
    }
        

    That gave me a pretty ugly dropdown list and didn't match up with the customer's definitions for those items and what they wanted to see in the UI. Then it hit me: I can use the DisplayAttribute and give each enumeration a "Name."

    public enum DeliveryMethod
    {
        [Display(Name = "Competitive Sealed Proposal")]
        CompetitiveSealedProposal,
        [Display(Name = "Construction Manager @ Risk")]
        ConstructionManagerRisk,
        [Display(Name = "Construction Manager - Agent")]
        ConstructionManagerAgent
    }
        

    Next, I added a function to extract the value from the DisplayAttribute:

    private static String GetText(Object e)
    {
        FieldInfo fieldInfo = e.GetType().GetField(e.ToString());
        DisplayAttribute[] displayAttributes = fieldInfo.GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[];
        return null != displayAttributes && displayAttributes.Length > 0 ? displayAttributes[0].Name : e.ToString();
    }
        

    Then I updated the extension to take advantage of the new function:

    public static IHtmlString DropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
        Type enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;
        IEnumerable<Object> enumValues = Enum.GetValues(enumType).Cast<Object>();
        IEnumerable<SelectListItem> items = from enumValue in enumValues
                                            select new SelectListItem
                                            {
                                                Text = GetText(enumValue),
                                                Value = ((Int32)enumValue).ToString(),
                                                Selected = enumValue.Equals(metadata.Model)
                                            };
        return html.DropDownListFor(expression, items, String.Empty, null);
    }
        

    Voila! Using the extension is as simple as this:

    @Html.DropDownListFor(m => m.DeliveryMethod)
        

    The extension also takes care of the selected value.