WebAPI REST Service (MVC Framework)

With the Web API I can easily create a REST service. Theoretically a REST service uses 4 different HTTP verbs to perform the basic CRUD operations on a particular entity. These verbs are:

GET This verb is used to read data
PUT This verb is most often used to update an existing entity
POST This verb is most often used to create a new entity
DELETE This verb is used to delete an entity

In practice what is often done (even why not all browsers support all the methods) is to use the GET verb to read/delete and the POST verb to create/update (we use the POST verb every time we have to send the whole object and not just the id).

Here is an example of a REST service made using a Web API controller:

[RoutePrefix("api/post")]
public class PostController : ApiController
{
    [HttpGet]
    [Route("get")]
    public List<PostModel> Get()
    {
        return new List<PostModel>()
        {
            new PostModel()
            {
                Title = "Post 1",
                Content = "Post 1 Content",
                DateCreated = new DateTime(2015,01,12)
            },
            new PostModel()
            {
                Title = "Post 2",
                Content = "Post 2 Content",
                DateCreated = new DateTime(2015,01,13)
            },
            new PostModel()
            {
                Title = "Post 3",
                Content = "Post 3 Content",
                DateCreated = new DateTime(2015,01,14)
            }
        };
    }
 
    [HttpPost]
    [Route("create")]
    public bool Create([FromBody]PostModel model)
    {
        //Save PostModel to DB
        return true;
    }
}

It can be easily referred by the client using the get()/post() JQuery methods, to invoke the service with the proper HTTP verbs:

<button id="getPost">GET</button>
<button id="createPost">POST</button>

@section scripts
{
    <script>
        $("#getPost").bind("click", function () {
            $.get("/api/post/get", function (data) {
                alert(data);
            });
        });
 
        $("#createPost").bind("click", function () {
            $.post("/api/post/create", {
                title: "Post 4",
                content: "post 4 content",
                dateCreated: "2014/01/16"
            },
            function (data) {
                alert(data);
            });
        });
    </script>
}

WebAPI 2 Controllers (MVC Framework)

Web APIs are a way to use controllers to return raw data instead of html. Even thought is possible to return JSon from a normal controller’s action, a Web Api allow us a more data oriented environment, with many features which allow us a more powerful approach on that direction.

To add a new Web API Controller to an existent MVC Web Application (is possible as well to add a dedicated Web API project to our solution) we can right-click on our Controllers folder (or on the folter we want to use for our Web API controllers) and the select Add -> Controller. From the Controller selection form we can choose to add a new “Web API 2 Controller Empty”.

Doing this some new references and files will be added to the solution, to allow us to work with Web APIs. In particular we will have a new WebApiConfig.cs file, that is for the WebAPIs what something similar at what the RouteConfig.cs is for the normal controllers. Here is how it looks like:

public static void Register(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();
 
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

To be sure that everything works we have to ensure that the Register() method is effectively called in the Global.asax file. It’s important that the method is called just after the RegisterAllAreas() method, otherwise we can have some issue with the routing configuration. Here is a example of how the Global.asax should look like:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

As we can see we have a call to the MapHttpAttributeRoutes() method, to have automatically enabled the route attributes (as the MapMvcAttibuteRoutes() method does for the normal controllers). The we have the default routing configuration for our Web API controllers. Even though a configuration is provided is highly recommended, especially when parameters are provided, to use the route attributes to specify every route.

Differently from the normal controllers, which can return JSon data by returning the result of the Json() method as action, in this case we are just returning the object with the result of our method. Here is an example:

[Route("api/forumApi/getIntListWithCount/{count}")]
public List<int> GetIntListWithCount(int count)
{
    var list = new List<int>();
    for (var n = 0; n < count; n++)
    {
        list.Add(n);
    }
    return list;
}

Managing the output format

If we try to invoke our Web API we’ll discover that probably our list will be returned in XML format. It should be better to have it on JSon format. In reality things are a little more complicated: Web APIs implements a negotiation mechanism which return the result object in different formats based on the request. Indeed we can invoke our method from the client side to have the result as JSon or as XML:

<script>
    $.ajax({
        dataType: "json",
        url: "/api/forumApi/getIntListWithCount/20",
        success: function (data) {
 
            //Data as JSon
            debugger;
        }
    });
    $.ajax({
        dataType: "xml",
        url: "/api/forumApi/getIntListWithCount/20",
        success: function (data) {
 
            //Data as XML
            debugger;
        }
    });
</script>

So the reason why, if we try to directly refer our Web API method from the browser, we’ll probably get the result with XML format, is because many browsers add the XML content format by default when asking for an html page (and of course the browser is asking for an html page by default). So how can we fix this? Fortunately we just have to add some extra configuration to our WebApiConfig.cs file:

public static void Register(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();
 
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
 
    //We set JSon as default format for any text/html request
    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(
        new MediaTypeHeaderValue("text/html"));
 
    //We configure a way to force the output format by adding ?type=json to
    //force the json format and by adding ?type=xml to force the XML format
    config.Formatters.JsonFormatter.MediaTypeMappings.Add(
        new QueryStringMapping("type", "json", new MediaTypeHeaderValue("application/json")));
    config.Formatters.XmlFormatter.MediaTypeMappings.Add(
        new QueryStringMapping("type", "xml", new MediaTypeHeaderValue("application/xml")));
}

Advanced routing (MVC Framework)

As we know the routing configuration of a MVC Framework application can be found within the RouteConfig.cs file. The default configuration is something like this:

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Which tells MVC Framework that we want to map an url like “/myController/myAction” to an action named “MyAction” of a controller named “MyControllerController”. The {id} parameter allows us to to send a parameter (optional in this case), called “id”, to our action. So an action like the following one is automatically handled by the default configuration and can be reached with this url: “/myController/GetTestObjectWithId/123”.

public ActionResult GetTestObjectWithId(int id)
{
    return Json(new
    {
        Name = "Test",
        Value = "TestValue",
        Id = id
    }, JsonRequestBehavior.AllowGet);
}

Defining a custom routing

If we need a custom routing we have to setup a specific rule to tell MVC Framework how to map the action with the desired url. For example let’s say that we want to reach the following action with this url “/myController/GetTestObjectWithParameter/123”:

public ActionResult GetTestObjectWithParameter(int parameter)
{
    return Json(new
    {
        Name = "Test",
        Value = "TestValue",
        Parameter = parameter
    }, JsonRequestBehavior.AllowGet);
}

This action looks very similar to the previous one, apart the parameter’s name. Well, this difference is enough to require us to define a custom routing rule. Indeed the default configuration uses a parameter called “id”, so if we try to refer this action with the url “/myController/GetTestObjectWithParameter/123” MVC Framework will not be able to map the token “123” of the url to the action’s parameter because it has a different name.

Without defining a custom routing the only way to reach this action is using this url “/myController/GetTestObjectWithParameter?parameter=123”. That is not as beautiful as the previous one.

So how can we define a custom routing rule? The classic way is to add another rule within the RouteConfig.cs file. Is important to insert any custom rule before the default one, because if many rules match the same url just the first one will be considered.

routes.MapRoute(
    name: "TestGetObjectWithParameters",
    url: "test/getTestObjectWithParameter/{parameter}",
    defaults: new { controller = "Test", action = "GetTestObjectWithParameter", parameter = @"\d+" });
 
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

With the @”\d+” configuration over the “parameter” parameter we are telling that it should fit the provided regular expression, so we want an integer parameter. Other options are available, see the documentation for a complete list.


Using the routing attibutes

From the version 5.0 of MVC Framework is possible to use another way to define custom route rules. We can use the routing attributes to associate an action with its route directly on the action’s definition, without writing anything on the RouteConfig.cs. In order to be able to take advantage of this feature we need to enable it from he RouteConfig.cs (before any other rule). This can be done using the MapMvcAttributeRoutes() method in this way:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapMvcAttributeRoutes();
 
    routes.MapRoute(
        name: "TestGetObjectWithParameters",
        url: "test/getTestObjectWithParameter/{parameter}",
        defaults: new { controller = "Test", action = "GetTestObjectWithParameter", parameter = @"\d+" }
    );
 
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

After enabled this feature we can easily assign a custom route to an action:

[Route("test/getTestObjectWithParameters/{parameter1}/{parameter2}")]
public ActionResult GetTestObjectWithParameters(int parameter1, int parameter2)
{
    return Json(new
    {
        Name = "Test",
        Value = "TestValue",
        Parameter1 = parameter1,
        Parameter2 = parameter2
    }, JsonRequestBehavior.AllowGet);
}

With attributes is possible to specify many behaviors, not just at action-level, but a controller-level as well. For example we can specify the route prefix for any action of the controller or the default action name. At action-level we can define if a parameter is optional (using “?”) or other constraints like the value type. See the documentation for a complete list of options.

Return JSon from an Action (MVC Framework)

I can return the JSon of any object from a common action by using the Json() method of the Controller class.

public class TestController : Controller
{
    public ActionResult GetTestObject()
    {
        return Json(new
        {
            Name = "Test",
            Value = "TestValue"
        }, JsonRequestBehavior.AllowGet);
    }
}

The AllowGet option tell MVC Framework that we want to be able to get this JSon from a get request on this action. Without it we’ll receive a runtime error, because by default MVC Framework won’t return any JSon content for security reasons.

Angular JS – Nesting Views with the “@” syntax (SPA Routing)

With the “@” syntax I can more easily define how nested states (or should be better to say nested views) should be managed. With this syntax I don’t have to define states for the templates, but just which view/controller I want to be displayed at any level of the templates hierarchy.

For example let’s imagine to have this main page:

<div ng-app="app">
    <div ui-view="">
    </div>
</div>

I can define a “root” state in this way:

$stateProvider.state("root", {
    url: "/",
    views: {
        "": {
            templateUrl: 'app/views/layout.html',
            controller: 'layoutController'
        },
        "topArea@root": {
            templateUrl: 'app/views/rootTopArea.html',
            controller: 'rootTopAreaController'
        },
        "bottomArea@root": {
            templateUrl: 'app/views/rootBottomArea.html',
            controller: 'rootBottomAreaController'
        },
        "bottomTopArea@root": {
            templateUrl: 'app/views/rootBottomTopArea.html',
            controller: 'rootBottomTopAreaController'
        },
        "bottomBottomArea@root": {
            templateUrl: 'app/views/rootBottomBottomArea.html',
            controller: 'rootBottomBottomAreaController'
        }
    }
});

What I’m saying is that for the view “” (the main one with no name) I want to load the layout.html view and I want to use the “layoutController” controller. Now let’s imagine that the layout.html view is made in this way:

<h2>This is the layout</h2>
{{value}}
 
<ul>
    <li>
        <div ui-view="topArea">
        </div>
    </li>
    <li>
        <div ui-view="bottomArea">
        </div>
    </li>
</ul>

Here we have two nested sub-view called “topArea” and “bottomArea”. With the “@” syntax I don’t have to specify new states (as when using the “.” syntax), but I just have to say that the “topArea” sub-view (for the “root” state, so “topArea@root”) should load the rootTopArea.html view and should use the “rootTopAreaController” controller. The same thing I’m doing for the “bottomArea” sub-view.

Finally let’s say that the rootBottomArea.html view is made in the same way as the layout.html view: with two sub-view inside. These are third level sub-views, so how should e manage this?

<h2>This is the root bottom area</h2>
{{value}}
 
<ul>
    <li>
        <div ui-view="bottomTopArea">
        </div>
    </li>
    <li>
        <div ui-view="bottomBottomArea">
        </div>
    </li>
</ul>

Simple, in the same way! We don’t need to follow the hierarchical structure of the sub-views’ tree, we just need to refer the sub-views’ names within our configuration. So we just have to specify the view and the controller for the “bottomTopArea@root” and the “bottomBottomArea@root” views.

And here is the final result:

Creating Bundles with MVC Framework

In an MVC Framework web application I can create multiple bundles from the App_Start/BundleConfig.cs file. Within that file I can define each bundle together with its content. I can as well to specify that all the files of a particular type included in a target folder should be added to the bundle.

Here is an example on how to define a bundle which contains two well specified JS files plus all the JS files from a particular folder:

bundles.Add(new ScriptBundle("~/bundles/angularApp").Include(
            "~/app/angularApp.js",
            "~/app/controllers/*.js",
            "~/app/statesConfig.js"));

To render a bundle within a Razor view I can use the @Script.Render (because in this case we have a script bundle) instruction:

@section scripts
{
    <script src="~/Scripts/angular.min.js"></script>
    <script src="~/Scripts/angular-ui-router.min.js"></script>
    @Scripts.Render("~/bundles/angularApp")
}

SignalR

Is a framework that we can use to easily manage the communication between different clients (e.g. for creating a chat). It defines the concept of hub, that is the central point towards which each client is connected. With SignalR we can share information between every client connected to the same hub. It uses OWIN (Open Web Interface for .Net) in order to work. SignalR uses different technologies to pursue its purpose: depending on the browser’s capabilities it can use web sockets or polling, with all the available optimizations.

First of all we have to add SIgnalR to our MVC Framework website. This can be done via NuGet:

Then we can add SignalR to an OWIN startup class to map it on the app builder pipeline. To do this we can create a class (in this example on the website root) in the following way:

using Microsoft.Owin;
using Owin;
 
[assembly: OwinStartup(typeof(ProvaSignalR.Startup))]
namespace ProvaSignalR
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

Now we can create our SignalR hub. A very interesting thing about hubs is that every method defined within them will be available on client side (through the server object of the client-side proxy auto-generated from its class). At the same way we can invoke any client-side method defined within the client object of the same proxy. With this hub we are telling that every time some client invoke our Send() method to post a new message, we have to broadcast the same message to all the clients, by calling their addNewMessageToPage() client-side method.

namespace ProvaSignalR.Hubs
{
    public class ChatHub : Hub
    {
        //Every method in this class will be
        //available for calling on client-side
        public void Send(string name, string message)
        {
            //We can call methods that are defined on client-side.
            //In this case we are calling the client-side method
            //addNewMessageToPage() for all the hub's clients
            Clients.All.addNewMessageToPage(name, message);
        }
    }
}

Finally, to test our chat, we can create a new action (e.g. “Chat”) with this related view:

@{
    ViewBag.Title = "Chat";
}
 
<h2>Chat</h2><div class="container">
    <input type="text" id="message" />
    <input type="button" id="sendmessage" value="Send" />
    <input type="hidden" id="displayname" />
    <ul id="discussion"></ul>
</div>
 
@section scripts {
    <script src="~/Scripts/jquery.signalR-2.1.2.min.js"></script>
 
    <!--
        This is the autogenerated SignalR hub script. It defines
        the proxy that we will use to communicate with the server
    -->
    <script src="~/signalr/hubs"></script>
 
    <script>
        $(function () {
 
            //Ask for the client name
            $('#displayname').val(prompt('Enter your name:', ''));
            $('#message').focus();
 
            //Create a reference to the hub proxy
            var chat = $.connection.chatHub;
 
            //Every method defined within the
            //client object of the proxy will be
            //available for calling on server-side
            chat.client.addNewMessageToPage = function (name, message) {
                $('#discussion').append('<li><strong>' + htmlEncode(name)
                    + '</strong>: ' + htmlEncode(message) + '</li>');
            };
 
            //Start the connection with the hub
            $.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
 
                    //We can call methods that are defined on
                    //server-side. In this case we are calling the
                    //server-side method Send() for the referenced hub
                    chat.server.send($('#displayname').val(), $('#message').val());
                    $('#message').val('').focus();
                });
            });
        });
 
        //This optional function html-encodes
        //messages for display in the page
        function htmlEncode(value) {
            var encodedValue = $('<div />').text(value).html();
            return encodedValue;
        }
    </script>
}

Testing with NUnit

To use the NUnit testing framework within a .Net project we have to create a normal Class Library Project (not a Unit Test Project, that is for the UnitTest Framework). Then we can add NUnit to the project via NuGet to start writing tests.

To write a test we have to create a class in the same way we do with UnitTest. NUnit offers some interesting functionality, such as the SetUp/TearDown methods, executed before/after each test, the possibility to have parametrized methods, and so on.

Here is an example in which we are testing an object who represent a range between two points and calculate its length:

//Additional NS
using NUnit.Framework;
using ProvaNUnit;
 
namespace MyTestLibrary
{
    public class MyRangeModelTest
    {
        [TestFixture]
        public class Given_A_MyRangeModel
        {
            private MyRangeModel _model;
 
            //The SetUp method will be
            //executed before each test
            [SetUp]
            public void SetUp()
            {
                _model = new MyRangeModel
                {
                    Point1 = 2,
                    Point2 = 10
                };
            }
 
            //This is a test
            [Test]
            public void It_Should_Calculate_The_Length()
            {
                Assert.AreEqual(_model.RangeLength, 8);
            }
 
            //This is a parametrized test. It will
            //be executed for each parameters set
            [Test]
            [TestCase(3, 8, TestName = "With_A_Forward_Range")]
            [TestCase(8, 3, TestName = "With_A_Backward_Range")]
            [TestCase(5, 5, TestName = "With_A_Empty_Range")]
            public void It_Should_Calculate_More_Lengths(int point1, int point2)
            {
                _model.Point1 = point1;
                _model.Point2 = point2;
 
                Assert.AreEqual(_model.RangeLength, Math.Abs(point2 - point1));
            }
 
            //The TearDown method will be
            //executed after each test
            [TearDown]
            public void TearDown()
            {
                _model = null;
            }
        }
    }
}

I can run NUnit tests directly from VS with Resharper. I can run a single test or the entire test set by right-clicking on the text editor. The results will be displayed in both the text editor and the Resharper Unit Test window.

Knockout JS – Custom Binding Handler to evaluate the content of an HTML Bind

With this custom Binding Handler we can have the binding over the content of an HTML Bind. So we can use data-bind attributes inside our bound HTML content.

ko.bindingHandlers.boundHTML = {
    init: function () {
        return { controlsDescendantBindings: true };
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        ko.applyBindingsToNode(element, { html: value });
        ko.applyBindingsToDescendants(bindingContext, element);
    }
};
<span data-bind="boundHTML: Content"></span>