Thursday, 22 March 2012

Cloud Foundry / Iron Foundry app & service limits

[Note this is correct for version 1.2 of the MCF/MIF]
If you're running Cloud Foundry (or Iron Foundry) locally (ie the "Micro" or MCF VMs), and you get this error when provisioning a service or application :

Error 504: Too many Services provisioned: 4, you're allowed: 4

Or

Error 601: Too many applications: 4, you're allowed: 4

Then you need to alter the config on your MCF instance.
This can be done by editing /var/vcap/jobs/cloud_controller/config/cloud_controller.yml

and altering the default values displayed below :


admin_account_capacity:
memory: 1024
app_uris: 32
services: 4
apps: 4
default_account_capacity:
memory: 512
app_uris: 8
services: 4
apps: 4

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.

Sunday, 4 March 2012

Alternative to MVC Routing

This dll takes some of the pain away from registering routes in ASP.NET MVC (including having to alter your routes when you rename a controller !)
It's on Nuget as "Mvc.Routing"

So instead of registering routes like this :

routes.MapRoute(
"foobar route",
"foo/{someParam}/bar",
new { controller = "Foo", action = "Bar" }
);



You can just call :

Routing.Register(typeof(MvcApplication).Assembly);



And then tag your controllers :

public class FooController : Controller
{
[Get("foo/{someParam}/bar")]
public ActionResult Bar(string someParam) {
// whatever
}
}



There are attributes for Get, Post, Put, Patch and Delete
The attributes behave like the normal HttpGet, HttpPost (etc) attributes - ie if you tag an action as Get(), then you can't post to it

You can use them in conjunction with the normal Http* attributes, for example :

public class FooController : Controller
{
[Get("foo/new")]
public ActionResult New() {
// whatever
}

[HttpPost]
public ActionResult Create(Bar bar) {
// whatever
}
}



If you don't use the HttpGet / HttpPost attributes for your actions, you can still register routes like so :

public class FooController : Controller
{
[Route("foo/{id}")]
public ActionResult View(Guid id) {
// whatever
}

[Route("foos")]
public ActionResult List() {
// whatever
}
}



Testing your routes is also pretty simple, below is an example using Mspec (Machine.Specifications) :



[Subject(typeof(TestController), "Given a test controller has marked the Index method as Get")]
public class when_registering_routes : register_route_context
{
Establish context = () =>
{
theExpectedRouteUrl = "all/routes/are/mine";
theExpectedActionName = "Index";
theExpectedControllerName = "Test";
};

Because of = () =>
{
Routing.Register(typeof(TestController).Assembly);
theRoute =
RouteTable.Routes.Select(x => x as Route).Where(x => x.Url == theExpectedRouteUrl).FirstOrDefault();
};

Behaves_like route_should_be_registered;
}


See the project specs here for more examples : https://github.com/benjaminkeeping/Mvc.Routing/tree/master/src/Mvc.Routing.Specs/registration