Tuesday, 13 March 2012

ASP.NET MVC4 Web API

Just checked out ASP.NET MVC4 Web API. Pretty impressed. We've been quite happily using OpenRasta so far for our restful stuff.
I'm not going to do full comparison, because I've not used web api in anger yet, and I don't want to be arguing for or against either frameworks, but here is some info on how to do some of the stuff you're going to want to know if considering a move from OpenRasta to ASP.NET MVC4's Web API (or perhaps just starting out in the resful framework space and have chosen Web API).

Pipelines
One thing I love about OpenRasta is the pipeline stuff - very easy.
But I have to say, Web API's making it pretty easy too ...
Note I'm injecting in a service ... its as easy as it should be


public class MyPipelineInterceptor : System.Net.Http.MessageProcessingHandler
{
readonly ISomeService _service;

public MyPipelineInterceptor(ISomeService service)
{
_service = service;
}

protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken)
{
return request;
}

protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken)
{
return response;
}
}



Dependancy Resolution
Again pretty darned easy, and I have to say (sorry Seb), easier to inject your favourite DI framework than OpenRasta 2's.
This is using Structuremap :


GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
t =>
{
try
{
return ObjectFactory.GetInstance(t);
}
catch (Exception)
{
return null;
}
},
t =>
{
try
{
return ObjectFactory.GetAllInstances(t).Cast<object>();
}
catch (Exception)
{
return new List<object>();
}
}

);


Pretty easy to configure :


GlobalConfiguration.Configuration.MessageHandlers.Add(new MyPipelineInterceptor(ObjectFactory.GetInstance<ISomeService>()));


Handlers
Handlers are minimal, and feel a lot like OpenRasta's.
Instead of OperationResult you have HttpResponseMessage.
The routing is handled automagically via a single call


routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);




public class ValuesHandler: ApiController
{
readonly ISomeService _someService;

public ValuesHandler(ISomeService someService)
{
_someService = someService;
}

public HttpResponseMessage Get()
{
return new HttpResponseMessage(new[] {"value1", "value2"}, HttpStatusCode.OK);
}

public HttpResponseMessage Get(int id)
{
return new HttpResponseMessage("value1", HttpStatusCode.OK);
}

public HttpResponseMessage Post(string value)
{
return new HttpResponseMessage(HttpStatusCode.Created);
}

public HttpResponseMessage Put(int id, string value)
{
return new HttpResponseMessage(HttpStatusCode.NoContent);
}

public HttpResponseMessage Delete(int id)
{
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
}




Pipeline injection
So one of the patterns we use (see https://github.com/agilex/agilex.persistence.openrasta) is injecting a repository into OpenRasta's CommunicationContext's PipelineData before any request, and disposing it after every request (kinda AOP style).
Chucking *global* resources into your pipeline is easy in Web API too ... in your interceptor (the first class in this post) :



request.Properties.Add("thing", new MyThing());


And then you can just access the properties in your handler/controller too, or on the response method on your pipeline interceptor.

So overall, pretty impressive so far.
As I said, I've not used it in anger yet, so not sure how it stacks up with trickier usuage (like complex model binding, or one-to-many route relationships - ie /users/123/orders), but to be fair, considering the model binding stuff is from asp.net mvc, and the routing is pretty similar, I'm sure it will be fine.

No comments:

Post a Comment