Creating your first ASP.Net Web API

2 comments:

This post looks at creating an API layer for an application. This post is part of a blog series ASP.Net 10 Years On. Even though this is part of a series I have tried to make each post standalone. In the previous post we discussed the merits of dropping the service layer in favour of an HTTP API. Now we look at creating this layer.

Introducing the Web API

The ASP.Net Web API shipped with ASP.Net MVC 4 and is a framework for building HTTP services. In particular it is a great tool for creating a RESTful application. If you have experience with MVC then using the Web API will be straight forward since the framework uses familiar concept such as controllers, routing etc. See the official website for beginner tutorials.

Getting Started

Taking the Users entity as an example let us dive into some code. A user entity has basic CRUD operations which need to be exposed via the HTTP API. This code is taken from the UsersController in the API project.

A tiny bit of REST

A very high level example of REST that will provide just enough detail to follow the below code snippets is to understand a resource and a verb. A resource is a representation of a thing. In our example the resource is a user entity. If we want to change the state of our resource we need some way of performing actions, or a verb. REST attempts to standardise these verbs so that all parties know what to expect when they are working with a resource.

The following table lists the HTTP verbs we will use and maps each verb to its usage.

Verb Usage Example Url
GET Used for getting data in a read only context. localhost/users OR localhost/users/<user_name> for a specific resource (think get by id).
POST Used to create a new resource. localhost/users/<user_name> with parameters of POST body containing parameters.
PUT Used to update an existing resource. localhost/users/<user_name> with parameters of PUT body containing parameters.
DELETE Used to delete a resource. localhost/users/<user_name>

NB REST is not simply the application of CRUD using the verbs GET, POST, PUT etc.

Code Example

The following code applies the REST principles previously outlined.

Starting with the simple "get all" and "get by id" methods the Web API actions would look as follows:

// GET users
public IEnumerable<UserItem> Get()
{
    var users = _userRepository.FindAll();
    return _mapper.Map<IEnumerable<User>, IEnumerable<UserItem>>(users);
}

// GET users/B5608F8E-F449-E211-BB40-1040F3A7A3B1
public UserItem Get(Guid id)
{
    var user = _userRepository.FindByID(id);
    if (user == null) throw new NotFoundException();
    return _mapper.Map<User, UserItem>(user);
}

Next we move onto creating a user. We need to use the HTTP verb POST to create a new resource:

// POST users
public HttpResponseMessage Post(CreateUserItem item)
{
    var user = new User()
    {
        Username = item.Username,
        Password = EncryptedString.Create(item.Password, _encryptionService)
    };

    if (user.IsValid)
    {
        _userRepository.Add(user);

        UserItem createdItem = _mapper.Map<User, UserItem>(user);
        return CreatedHttpResponse(createdItem.ID, createdItem);
    }

    return Request.CreateResponse(HttpStatusCode.BadRequest, user.ValidationErrors);
}

Note that when using POST and creating a new resource the HTTP REST convention states that we must indicate a successful action by returning the HTTP response for a created item.

To update an existing resource the PUT verb would be used:

// PUT users/B5608F8E-F449-E211-BB40-1040F3A7A3B1
public HttpResponseMessage Put(Guid id, UpdateUserItem item)
{
    User user = _userRepository.FindByID(id);

    if (user == null) throw new NotFoundException();

    user.Username = item.Username;

    if (user.IsValid)
    {
        _userRepository.Update(user);
        return Request.CreateResponse(HttpStatusCode.OK);
    }

    return Request.CreateResponse(HttpStatusCode.BadRequest, user.ValidationErrors);
}

To delete a resource we will make use of the DELETE verb:

// DELETE users/B5608F8E-F449-E211-BB40-1040F3A7A3B1
public HttpResponseMessage Delete(Guid id)
{
    var user = _userRepository.FindByID(id);

    if (user == null) throw new NotFoundException();

    _userRepository.Remove(user);

    return new HttpResponseMessage(HttpStatusCode.NoContent);
}

Note the HTTP status codes used are specific for each type of action.

How do I…?

Use Dependency Injection?

In the example code I'm using the repository pattern, which means that if I want to keep my class dependencies de-coupled or write unit tests for my methods I need a way of injecting the class dependencies into my controller class. Ninject is my IoC container of choice, but it's not so straight forward to use Ninject and the the Web API. Rather than re-explaining take a look at this excellent article from Peter Provost that details how to add Ninject to Web API.

Unit Test a Controller Action?

Writing unit tests is pretty straight forward until you want to verify anything related to the Request/Response objects of the controller.

To test a get method, a unit test such as the following would suffice:

// Tests that a user entity is returned.
[TestMethod]
public void GetUserByIDReturnsUser()
{
    // Arrange
    var repo = new Mock<IUserRepository>();
    repo.Setup(s => s.FindByID(It.IsAny<Guid>())).Returns(GetUserResponse());
    var controller = new UsersController(repo.Object);

    // Act
    UserItem response = controller.Get(Guid.NewGuid());

    // Assert
    Assert.IsNotNull(response);
}

If we move on to test the create new User action our test code might look as follows:

/// <summary>
/// Posting the user returns HTTP created status.
/// </summary>
[TestMethod]
public void PostUserReturnsHttpCreatedStatus()
{
    // Arrange
    var repo = new Mock<IUserRepository>();
    repo.Setup(s => s.Add(It.IsAny<User>()));

    var controller = new UsersController(repo.Object);

    // Act
    HttpResponseMessage response = controller.Post(new CreateUserItem());
    
    // Assert
    Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
}

The problem with this test is that you will encounter a Null Reference exception caused by the call to Request.CreateResponse (see the POST method we discussed earlier to reference code under test). We encounter this because the controller in question has dependencies that need to be mocked in order to assert the state of these instances. Since these will be null as we are creating a new controller instance for our tests we need a way of initialising these dependencies along with the controller. Peter Provost to the rescue again with his brilliant post: Unit Testing ASP.Net Web API.

Here is my tweaked implementation to work with my style of writing unit tests using MSTest.

public class ControllerSetup
{
    /// <summary>
    /// Registers the context.
    /// </summary>
    /// <param name="controller">The controller.</param>
    /// <param name="controllerName">Name of the controller.</param>
    public static void RegisterContext(ApiController controller, string controllerName)
    {
        var config = new HttpConfiguration();
        var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/" + controllerName);
        var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
        var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", controllerName } });

        controller.ControllerContext = new HttpControllerContext(config, routeData, request);
        controller.Request = request;
        controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;
        controller.Request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
    }
}

I need to revisit the test in question and add a line of code to call my ControllerSetup method and my test will now run without error:

/// <summary>
/// Posting the user returns HTTP created status.
/// </summary>
[TestMethod]
public void PostUserReturnsHttpCreatedStatus()
{
    // Arrange
    var repo = new Mock<IUserRepository>();
    repo.Setup(s => s.Add(It.IsAny<User>()));

    var controller = new UsersController(repo.Object);

    // *** Newly added line to register the controller context.
    ControllerSetup.RegisterContext(controller, "users");
    // ***

    // Act
    HttpResponseMessage response = controller.Post(new UserItem());
    
    // Assert
    Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
}

Catch Errors?

Something I quickly spotted when debugging is that an unhandled exception would reveal the full trace e.g.

"Message": "An error has occurred.", "ExceptionMessage": "The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_Competitions_Users\". The conflict occurred in database \"SmsQuiz\", table \"dbo.Users\", column 'ID'."

… remaining text removed for brevity.

It is dangerous to reveal such detail in a public facing API. To catch exceptions and display limited information I use the following filter attribute:

public class UnhandledExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        context.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
    }
}

I now decorate the controller class in question:

[UnhandledException]
public class UsersController
{
 // class detail here….
}

For further detail see Exception Handling in ASP.Net Web API.

Validate Models?

Validation in the code snippets of this post takes place in the domain model. However, not all projects need a domain model. The following article explains how validation can be achieved using data annotations that will be very familiar to LinqToSql or Entity Framework users. Here is the article: Validating your models in ASP.Net Web API.

Useful Tools

Fiddler

You are going to be doing a lot of HTTP debugging so a good HTTP debugging tool is essential! Fiddler is one of the best tools around - and it's free!

SOAP UI

Allows for API testing via a GUI i.e. no code required! See the official website.

Further Reading

For more tutorials on REST: http://rest.elkstein.org
For more detail on how to use HTTP status codes: https://github.com/basho/webmachine/wiki/Diagram
HTTP spec: http://www.w3.org/Protocols/rfc2616/rfc2616.html

Why algorithm performance matters more than ever

No comments:
Wanted

It has always been a requirement to write efficient code. Most job ads desire it, university courses teach it and there are countless books available on the subject. But, how efficient is your code? How much CPU time does that parse method you wrote use? How much memory does that search algorithm you wrote consume? How many calls to that 3rd party API you are making per hour and how many read/writes are you making to your database? I've written a couple of applications using Google App Engine recently and the breakdown of billing resources will answer all of the previous questions and more with a monetary amount!

With the rise of cloud computing providers and the trend towards it, it will soon be possible to put an exact price on just how efficient your code is! In terms of performance it will be possible to put a price on your head! There will be no hiding place and any performance mistakes and bad algorithms could be costly, literally! Every aspect of application design will be scrutiny to billing itemisation ranging from CPU time, memory usage and database connectivity. We have nowhere to hide.

If you've shied away from performance then now is the time to sharpen the saw. If you've yet to discover coursera.org, I highly recommend it. In the context of this post, if you want to sharpen your algorithm performance skills then enrol on this free course: Algorithms, Part 1. It started on the 4th Feb, but there is plenty of time to catch up.

Replacing the Service Layer with an HTTP API

1 comment:

This post looks at choosing a service layer for a web application. This post is part of a blog series ASP.Net 10 Years On. Even though this is part of a series I have tried to make each post standalone. In the previous post we wrapped up the data access layer and look to move onto the API layer.

9 out of 10 architectures I have worked with have had service layer projects with classes called SomethingService e.g. ProductService that contained methods such as GetProducts, GetProductByID etc.

Such methods can be easily be exposed for an API by converting the methods into messages such as SOAP or using .Net features such as Remoting.

In the architecture for our SMS Quiz we started off with a service layer that would serve a double purpose of firstly powering a REST API and a Website layer (MVC project). The idea was to avoid duplicate code between the Web and API layer.

Here's a diagram of how it looked (the application layer is the service layer):

Before we look to create an API layer for the quiz application to expose the functionality provided by the service layer let's consider the number of layers we have and how (potentially) similar they are.

As I began to flesh out the code and unit tests for the API and Web layers I noticed a lot of similarities between the two. The controllers were very similar and each project had almost identical sets of unit tests.

Here's an example of the similar looking methods. All these methods are very short, since the service layer is doing the real work.

An example method from an MVC controller:

public ActionResult Index()
{
    CompetitionViewModel viewModel = new CompetitionViewModel();
    viewModel.Competitions = _competitionService.GetCompetitions().Competitions;
    return View("Index", viewModel);
}

Now, an almost identical method in the Web API project:

public IEnumerable<CompetitionItem> Get()
{
    return _competitionService.GetCompetitions().Competitions;
}

As well as the near duplicate methods there is also a bunch of duplicate configuration such as Ninject bindings for dependency injection, mapper configuration, logging etc that are required when creating instances of service layer classes. So, what's the solution? It's easy: delete stuff!

By making the Web API the service layer also we can remove all configuration elements from the MVC project, merge the service layer code into the API and delete the service layer completely. This means that we can use HTTP as the transport protocol and we can consume the same API we plan to expose externally, internally; otherwise known as eating your own dog food.

Here's how the new architecture looks:

Http api layer

The updated Web API controller methods now look more like the service layer methods i.e. they use the repository layer and mapping:

public IEnumerable<CompetitionItem> Get()
{
    var competitions = _competitionRepository.Find("Status=@Status", new { Status = CompetitionStatus.Open });
    return _mapper.Map<IEnumerable<Competition>, IEnumerable<CompetitionItem>>(competitions);
}

The updated MVC action methods now resemble something like:

public ActionResult Index()
{
    var response = _client.GetAsync("competitions").Result;

    if (response.IsSuccessStatusCode)
    {
        dynamic users = response.Content.ReadAsAsync<dynamic>().Result;
        return View(users);
    }

    return ErrorView(response);
}

The beauty of this approach is that, other than a URL, the MVC layer requires no extra configuration. Adopting principles of REST with regard to statelessness combined with this approach can also make scaling out and load balancing a little easier.

Our web layer is now platform independent. Do we even need server side code for the web project? We can very easily use a client-side library like Backbone.js or Knockout.js without having to make any changes to the API.

As well has having an architecture that's easier to scale and requires less configuration I also got to delete a few projects from the solution making my project more streamlined yet more capable. Win!

NB future blog posts will take a deeper dive into the technical aspects of this approach.

The source code for this (work in progress) project can be found at: github.com/bbraithwaite/smsquiz.

Key code elements discussed in this post:

In the next post we look at creating the Web API.

Win a Telerik JustMock License

No comments:

Want a chance to win a free copy of the JustMock mocking framework worth $399 / €299 / £250 by Telerik?

I wrote a blog post titled Top 5 TDD Mistakes for the Just* Team Blog which you can read here. Be sure to comment on the post and share your top TDD mistakes! As a gesture of good will Telerik have provided me with 3 licences to giveaway and I'm sharing them with you.

Simply tweet the following and a winner will be selected at random:

Retweet for a chance to win a Telerik JustMock license worth $399. 3 to giveaway. http://goo.gl/14XjC #TDDMistakes via @contentedcoder

NB you MUST cut and paste the tweet text as-is and ensure it includes the hashtag.

Or, you can see the original tweet here.

Note: I will DM the winners a license code via Twitter and will ask for the winners to tweet to verify if they are willing! Feel free to follow me via @contentedcoder for updates.

Good Luck!

Note: standard competition rules apply. Your details will not be shared and you will only be contacted if you have won. Competition closes on Thursday 31st Jan 2013 at 12 pm GMT.