Ioannis Panagopoulos blog

Tutorials on HTML5, Javascript, WinRT and .NET

Implementing a JSON REST service with ASP.NET MVC

by Ioannis Panagopoulos

Two years ago, I have written a post about implementing a REST service using WCF. Back then, I didn't know that I was referring to services over the HTTP protocol which are not necessarily REST. Nevertheless, since it seems (from my blog analytics point of view) that people out there when they search for REST services actually imply services over the HTTP protocol or not SOAP more generally I kept the same title in this post.

The point is that you have some kind of client code in javascript and you need to implement in ASP.NET MVC a bunch of services that support getting/putting data from/to your database. In this post we will see how to take advantage of ASP.NET MVC 3 to implement such a JSON service and explore how you can pass data back and forth. I could write this post for ASP.NET MVC4 but in many ways I believe that knowning how to do that in ASP.NET MVC3 helps you understand a lot of the automations that the new MVC version has brought to the picture. Taking also advantage of the WebAPI in ASP.NET MVC4 is an option as long as you realize that the WebAPI supports and sometimes enforces some rules related to the pure "REST" protocol which are not always required.

So in this blog post, simplicity and crude direct appoach are the two motivators behind the proposed solution.

Create a new empty ASP.NET MVC 3 project (empty). Get rid of all the "Contents" folder and leave only the "jquery.min" definition in the Scripts folder (we are keeping this for testing our service)

Create a Controller named "ServicesController" for the services and a controller named "TestingController" for the tests.

Getting .NET objects as JSON (Demo1 Action)

Create and action named in both the "Services" and the "Testing" controllers. Create a view for the "Demo1" action in the "Testing" controller as follows:

    $(document).ready(function () {
        $.get('@Url.Action("Demo1","Services")', {Param1:12,Param2:'John'}, function (data) {
            console.log(data);
        });
    });				
				

In order to support this king of request the passes the parameters "Param1,Param2" to the service and has the JSON object in the "data" parameter the "Demo1" action in the "Services" controller is as follows:

public class Demo1Class
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public List<int> SomeList { get; set; }
}

public JsonResult Demo1(int? Param1,string Param2)
{
    Demo1Class Obj = new Demo1Class();
    Obj.Name = Param2;
    Obj.Surname = Param2;
    Obj.SomeList = new List<int>();
    Obj.SomeList.Add(Param1.GetValueOrDefault());
    return Json(Obj, JsonRequestBehavior.AllowGet);
}
				

Note that with define the parameters as nullable so the action can run even if the client has not supplied them. Also note that there is no need to define the return class. We could just write the code below and still get the required result:

public JsonResult Demo1(int? Param1,string Param2)
{
	List<int> SomeList=new List<int>();
	SomeList.Add(Param1.GetValueOrDefault());
	return Json(new{Name=Param2,Surname=Param2,SomeList=SomeList}, JsonRequestBehavior.AllowGet);
}
				

Sending .NET objects (Demo2 Action)

Now let's say you have the following javascript:

$(document).ready(function () {
    var client = {
        name: 'John',
        surname: 'Panagopoulos',
        age: 37,
        values:[11,22,111,2,87]
    };
    $.get('@Url.Action("Demo2","Services")', { id: 11, client: client }, function (data) {
        console.log(data);
    });
});			
				

Developing the following service action (Demo2) will not work.

public class Demo2Class
{
    public string name { get; set; }
    public string surname { get; set; }
    public int age { get; set; }
    public List<int> values { get; set; }
}
public JsonResult Demo2(int? id, Demo2Class client)
{
    // Some server side logic
    return Json(new { result=true }, JsonRequestBehavior.AllowGet);
}

				

This maps the names of the parameters and the properties of the object one by one with the ones passed from the javascript. But it does not work well with the object due to a limitation in the ASP.NET MVC model binder. There are many solutions to that. For me the most straightforward is to include a small jquery extension called $.toDictionary (see also this post) in your html and wrap the parameters with this as follows:

$(document).ready(function () {
    var client = {
        name: 'John',
        surname: 'Panagopoulos',
        age: 37,
        values:[11,22,111,2,87]
    };
    $.get('@Url.Action("Demo2","Services")',$.toDictionary({ id: 11, client: client }), function (data) {
        console.log(data);
    });
});			
				

Note that this can work even if you have nested objects.

Alternatively, you can send the previous request via POST as follows (the ajax command is used in this case so you can also set the cache parameter)

$.ajax({
    url: '@Url.Action("Demo2Post","Services")',
    type: "POST",
    data: $.toDictionary({ id: 11, client: client }),
    success: function (data) {
        console.log(data);
    },
    cache: false
});
				

Your service method in this case is the same as the previous one with the only difference that you need to decorate the action with the [HttpPost] attribute.

And this is it. Now you know how to send,get results from actions that return JSON data using either GET or POST. The demo project can be downloaded here

blog comments powered by Disqus
hire me