Monday, February 27, 2012

Using StructureMap with Web API

To inject dependencies into your ASP.NET Web API controller we need to use the Web API dependency resolver. It is similar to the MVC 3 IDependencyResolver interface definition.

In the blog post I'll create a custom dependency resolver using StructureMap.

Firstly we need to create a class that inherits from IDependencyResolver which resides in the namespace System.Web.Http.Services.



Code Snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Services;
using StructureMap;

namespace WebApi.Dependency
{
    public class StructureMapDependencyResolver:IDependencyResolver
    {
        public StructureMapDependencyResolver(IContainer container)
        {
            _container = container;
        }

        public object GetService(Type serviceType)
        {
            if (serviceType.IsAbstract || serviceType.IsInterface)
                return _container.TryGetInstance(serviceType);

            return _container.GetInstance(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
        }

        private readonly IContainer _container;
    }
}



To register this with Web Api we use the Global.asax file with the Application_Start method insert the following code.


Code Snippet

var container = ObjectFactory.Container;
            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
                new StructureMapDependencyResolver(container));



so that the Application_Start method looks like


Code Snippet

        protected void Application_Start()
        {

            var container = ObjectFactory.Container;
            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
                new StructureMapDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            BundleTable.Bundles.RegisterTemplateBundles();
        }



Now we can have controllers that use dependency injection.




Code Snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using NHibernate.Linq;
using WebApi.Data.Configuration;
using WebApi.Data.Models;

namespace WebApi.Controllers
{
    public class WorkoutController : ApiController
    {
        private readonly IUnitOfWork _unitOfWork;

        public WorkoutController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        // GET /api/workouts
        public IEnumerable<Workout> Get()
        {
            return _unitOfWork.CurrentSession.Query<Workout>().AsEnumerable();
        }

        // GET /api/workout/5
        public Workout Get(Guid id)
        {
            return _unitOfWork.CurrentSession.Query<Workout>().FirstOrDefault(x => x.Id == id);
        }

        // POST /api/workouts
        public HttpResponseMessage<Workout> Post(Workout workout)
        {
            var id = _unitOfWork.CurrentSession.Save(workout);
            _unitOfWork.Commit();

            var response = new HttpResponseMessage<Workout>
                (workout, HttpStatusCode.Created);
            response.Headers.Location = new Uri(Request.RequestUri,
                Url.Route(null, new { id }));

            return response;
        }

        // PUT /api/workouts/5
        public Workout Put(Guid id, Workout workout)
        {
            var existingWorkout = _unitOfWork.CurrentSession.Query<Workout>().FirstOrDefault(x => x.Id == id);

            if(existingWorkout==null)
                throw new HttpResponseException(HttpStatusCode.NotFound);

            _unitOfWork.CurrentSession.Update(workout);
            _unitOfWork.Commit();
        }

        // DELETE /api/workouts/5
        public HttpResponseMessage Delete(Guid id)
        {
            var existingWorkout = _unitOfWork.CurrentSession.Query<Workout>().FirstOrDefault(x => x.Id == id);

            if(existingWorkout==null)
                return new HttpResponseMessage(HttpStatusCode.NoContent);

            _unitOfWork.CurrentSession.Delete(existingWorkout);

            _unitOfWork.Commit();

            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }
    }
}



Happy Api creating.

Friday, February 24, 2012

Using knockout.mapping Plugin with Asp .Net MVC – Part 1a

In part 1 of this series I explored knockoutjs and completed a simple display view in the UI.

A few people have spoken to me about the implementation and commentated on what they perceived as a leakage into the Separation of Concerns regarding how bindings are managed via the data-bind attributes. While the comments certainly led to some interesting debates, I thought how can I remove some of those Concerns away from the UI.

Some research and I came across Neil Kerkin's blog post Exploring TodoMVC and knockout.js with unobtrusive bindings where he discusses an approach using knockout.js supports custom binding providers that allow us to refactor the code to achieve a bit more separation.

I won't go too much into what I have done because Neil explains it a lot better than I could. Therefore I'll just post the newer code base that will be used for part 2.

The javascript which looked like the following:

Code Snippet

(function (getworkouts, $, undefined) {    //create view model and initialise with default data.
    getworkouts.viewModel = function() {
        this.workouts = ko.mapping.fromJS(
                    [],
                    {
                        key: function (workout) { return ko.utils.unwrapObservable(workout.Id); }
                    });
                };    //use ajax call to populate the view model from the Action and also bootstraps knockout
    getworkouts.getDataFromSource = function () {
        $.ajax({
            type: 'POST',
            url: '/Home/GetWorkouts',
            dataType: 'json',
            success: function (data) {
                var model = new getworkouts.viewModel();
                model.workouts = ko.mapping.fromJS(data);
                ko.applyBindings(model);
            }
        });
    };
} (window.getworkouts = window.getworkouts || {}, jQuery));$(document).ready(function () {
    //bootstrap call
    getworkouts.getDataFromSource();
});


becomes

Code Snippet



/* File Created: February 5, 2;01;2 ;*/

(function (getworkouts, $, undefined) {

    window.setUpBindings.SetCustomBindings();

    //create view model and initialise with default data.

    getworkouts.viewModel = function () {

        this.workouts = ko.mapping.fromJS(

                    [],

                    {

                        key: function (workout) { return ko.utils.unwrapObservable(workout.Id); }

                    });

    };

    //use ajax call to populate the view model from the Action and also bootstraps knockout

    getworkouts.getDataFromSource = function () {

        $.ajax({

            type: 'POST',

            url: '/Home/GetWorkouts',

            dataType: 'json',

            success: function (data) {

                var model = new getworkouts.viewModel();

                model.workouts = ko.mapping.fromJS(data);

                getworkouts.bindings = {

                    workouts: { foreach: model.workouts },

                    workoutsDateTime: function () { return { text: this.DateTime }; },

                    workoutsWorkoutName: function () { return { text: this.WorkoutName }; }

                };

                //set ko's current bindingProvider equal to our new binding provider

                ko.bindingProvider.instance = new ko.customBindingProvider(getworkouts.bindings);

                ko.applyBindings(model);

            }

        });

    };

} (window.getworkouts = window.getworkouts || {}, jQuery));

$(document).ready(function () {

    //bootstrap

    getworkouts.getDataFromSource();

});

    



With an additional javascript snippet of

Code Snippet



/* File Created: February 16, 2012 */

(function (setupBindings, $, undefined) {

    setupBindings.SetCustomBindings = function() {

        ko.customBindingProvider = function(bindingObject) {

            this.bindingObject = bindingObject;

            //determine if an element has any bindings

            this.nodeHasBindings = function(node) {

                return node.getAttribute ? node.getAttribute("data-class") : false;

            };

            //return the bindings given a node and the bindingContext

            this.getBindings = function(node, bindingContext) {

                var result = { };

                var classes = node.getAttribute("data-class");

                if (classes) {

                    classes = classes.split(' ');

                    //evaluate each class, build a single object to return

                    for (var i = 0, j = classes.length; i < j; i++) {

                        var bindingAccessor = this.bindingObject[classes[i]];

                        if (bindingAccessor) {

                            var binding = typeof bindingAccessor == "function" ? bindingAccessor.call(bindingContext.$data) : bindingAccessor;

                            ko.utils.extend(result, binding);

                        }

                    }

                }

                return result;

            };

        };

    };

} (window.setUpBindings = window.setUpBindings || {}, jQuery));



The view then becomes

Code Snippet



<tableclass="gridtable">

    <thead>

        <tr>

            <th>

                Date Of Workout

            </th>

            <th>

                Name Of Workout

            </th>

        </tr>

    </thead>

    <tbody data-class="workouts">

        <tr>

            <td>

                    <span data-class="workoutsDateTime"></span>

            </td>

            <td>

                    <span data-class="workoutsWorkoutName"></span>

            </td>

        </tr>

    </tbody>

</table>



Once again the code is available at Github.

I've rushed over the implementation mainly because I don't want to any credit away from Neil Kerkin's solution to the Separation of Concerns problem.

See you at part 2.

Saturday, February 18, 2012

First MVC and now Web Api Microsoft is on a roll

The newly release Web Api is the next version of the excellent WCF Web API.

ASP.NET Web API is a framework for building and consuming HTTP services that can reach a broad range of clients including browsers and mobile devices. It’s also a great platform for building RESTful services. ASP.NET Web API takes the best features from WCF Web API and merges them with the best features from MVC.

The integrated stack supports the following features:

  • Modern HTTP programming model

  • Full support for ASP.NET Routing

  • Content negotiation and custom formatters

  • Model binding and validation

  • Filters

  • Query composition

  • Easy to unit test

  • Improved Inversion of Control (IoC) via DependencyResolver

  • Code-based configuration

  • Self-host


More information can be found at Web Api. the official Microsoft Web Api web site.

Over the past 11 years I've used asmx web services, ashx handlers and WCF services to build consumable web services. Recently I've ditched WCF as being too cumbersome and configuration heavy to use MVC as a poor man's Web service provider. Using Action Filters to create XML and JSON outputs dependent on the client request it made developing web service endpoints so much easier.

Now with the new Web Api solution from Microsoft all the MVC goodness (routes etc) and the good bits from WCF Web Api seems to have given a solid Web Services base to build robust .Net Apis with ease.

Initial set up is relatively easy either via NuGet or the ASP MVC 4 beta release installer

I'll endeavour to get a sample up very soon, hopefully as part of my Knockout js series.

In the meantime go to the Web Api home page or have a look at Jon Galloway's blog, ASP.NET MVC 4 Beta Released!, which contains an informative section on the ASP.NET Web API.

Tuesday, February 7, 2012

Using knockout.mapping Plugin with Asp .Net MVC - Part 1

Knockout is a JavaScript library that makes it easier to create rich, desktop-like user interfaces with JavaScript and HTML, using observers to make your UI automatically stay in sync with an underlying data model.

In this post I am going to show how ASP .Net MVC and Knockout can compliment each other to allow for a rich client side user experience.

Starting with an Empty MVC 3 application in Visual Studio let's start with some dependencies:
PM> install-package knockoutjs

PM> install-package Knockout.Mapping
PM> update-package //running this last command will update bundled packages that MVC 3 comes with (jQuery etc).

Installing the above packages will give you the javascript files required for Knockout and the Knockout Mapping plugin.

I highly recommend reading the documentation on the Knockout js site for a solid background of what Knockout can do to help solve client side functionality problems.

Now that we have the pre-requisites let's build a model to interact with:


Code Snippet

public class Workout
    {
        public long Id { get; set; }
        public string DateTime { get; set; }
        public string WorkoutName { get; set; }
    }



Now that we have a model we need to present it to the user.

Let's start with a view that shows all workouts in a tabular format. The html output I want is as such:

Html Layout for Knockout

To achieve that I need to replicate the html code as follows:


Code Snippet



  1. <table class="gridtable">

  2.     <thead>

  3.         <tr>

  4.             <th>

  5.                 Date Of Workout

  6.             </th>

  7.             <th>

  8.                 Name Of Workout

  9.             </th>

  10.         </tr>

  11.     </thead>

  12.     <tbody>

  13.         <tr>

  14.             <td>

  15.                 24/12/2011

  16.             </td>

  17.             <td>

  18.                 Full Body Workout 1a

  19.             </td>

  20.         </tr>

  21.         <tr>

  22.             <td>

  23.                 25/12/2011

  24.             </td>

  25.             <td>

  26.                 Full Body Workout 2a

  27.             </td>

  28.         </tr>

  29.     </tbody>

  30. </table>





Let's set up a Action on the Home controller to return a JsonResult.




Code Snippet



  1. public JsonResult GetWorkouts()

  2.         {

  3.             var model = new List<Workout>

  4.                             {

  5.                                 new Workout

  6.                                     {DateTime = DateTime.Now.AddDays(-7).ToShortDateString(), Id = 1, WorkoutName = "Full Body Workout 1a"},

  7.                                 new Workout

  8.                                     {DateTime = DateTime.Now.AddDays(-6).ToShortDateString(), Id = 2, WorkoutName = "Full Body Workout 2a"}

  9.                             };

  10.  

  11.             return Json(model);

  12.         }





Now for the javascript to initalise knockout and set up the inital data for the view model.



Code Snippet

(function (getworkouts, $, undefined) {

    //create view model and initialise with default data.
    getworkouts.viewModel = function() {
        this.workouts = ko.mapping.fromJS(
                    [],
                    {
                        key: function (workout) { return ko.utils.unwrapObservable(workout.Id); }
                    });
                };

    //use ajax call to populate the view model from the Action and also bootstraps knockout
    getworkouts.getDataFromSource = function () {
        $.ajax({
            type: 'POST',
            url: '/Home/GetWorkouts',
            dataType: 'json',
            success: function (data) {
                var model = new getworkouts.viewModel();
                model.workouts = ko.mapping.fromJS(data);
                ko.applyBindings(model);
            }
        });
    };
} (window.getworkouts = window.getworkouts || {}, jQuery));

$(document).ready(function () {
    //bootstrap call
    getworkouts.getDataFromSource();
});



As you can see I use a Self-Executing Anonymous Function to help protect the global namespace.

Let's dissect the javascript.

First we create a public property on the View Model called workouts, this will store the array of workouts to be displayed to the client. Next we create a bootstrapping function, see the function named getDataFromSource. This makes a jQuery ajax call to /Home/GetWorkouts, an action on the Home controller that returns a JsonResult which represents the data to be presented. The line model.workouts = ko.mapping.fromJS(data); is particularly interesting. The mapping plugin for Knockout gives you a straightforward way to map a plain JavaScript object into a view model with the appropriate observables. This provides an alternative to manually writing your own JavaScript code to construct the view model. That is instead of writing a lot of boilerplate code you can write one line and get on with writing the rest of your application. Finally calling ko.applyBindings(model); initialises knockout.

All that is needed now is the UI set up.




Code Snippet

<table class="gridtable">
    <thead>
        <tr>
            <th>
                Date Of Workout
            </th>
            <th>
                Name Of Workout
            </th>
        </tr>
    </thead>
    <tbody data-bind="foreach: workouts">
        <tr>
            <td><span data-bind="text: DateTime"></span></td>
            <td><span data-bind="text: WorkoutName"></span></td>
        </tr>
    </tbody>
</table>



This will iterate over the workouts property and produce the relevant tr elements and text to produce Html as we were expecting.

The source code is available here at github

My next post in this series will add Edit/Delete functionality to the application until then I hope that this post has presented the reader with an overview of a possible approach for a real life knockout and MVC 3 based application.