0

In an MVC3 application, I need to construct a domain object from values contained in the incoming Http Request. The logic is sufficiently complex that I have created a factory class with the responsibility of creating my domain object.

My question is whether to pass into this factory class the value of the Controller's Request property, or should I reference the value of the static HttpContext.Request property from inside the factory class?

My intention is to unit test both the controller and the factory class so I will have perform the necessary overhead of setting up the HttpContext somewhere. I just wondered if there are any general rules to stick to?

Nick
  • 6,366
  • 5
  • 43
  • 62

1 Answers1

2

Simply pass a NameValueCollection to your factory class:

public SomeDomainObject ConstructDomainObject(NameValueCollection data)
{
    ...
}

and then in your controller simply:

var domainModel = factory.ConstructDomainObject(Request.Params);

Now you can unit test the ConstructDomainObject method as much as you like.

If you want to test your controller in isolation then make have this factory object implement an interface:

public interface IMyFactory
{
    SomeDomainObject ConstructDomainObject(NameValueCollection data);
}

that your controller will work with:

public class SomeController: Controller
{
    private readonly IMyFactory factory;  
    public SomeController(IMyFactory factory)
    {
        this.factory = factory;
    }

    public ActionResult SomeAction()
    {
        var domainModel = this.factory.ConstructDomainObject(Request.Params);
        ...
    }
}

All this being said, have you considered writing a custom model binder? In ASP.NET MVC the responsibility of the model binder is exactly that: instantiate some model from the request. This way you don't need to be reinventing some wheels but you will be using what's natively built into the framework for this purpose.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Ok, Request.Params is very helpful here, thanks. What is your reason for doing it this way as opposed to just using the static HttpContext.Current.Request? – Nick Feb 19 '13 at 13:52
  • I have considered using a model binder, but I am performing this logic in the overriden OnActionExecuting method on my base controller as I need to make sure it is called before all my action methods. Is there a way to get the object created by model binding from inside OnActionExecuting? – Nick Feb 19 '13 at 13:57
  • @Nick Because then your factory becomes harder to test and it is tightly coupled to the HttpContext. If you are passing in a NameValueCollection then anything could use this factory. – Dismissile Feb 19 '13 at 14:32
  • @Nick, `HttpContext.Current`? Really? And you are asking about unit testing :-) Never use `HttpContext.Current` anywhere. And to answer your question `Is there a way to get the object created by model binding from inside OnActionExecuting` : Yes, there is a way. Simply read it from the action descriptor context. – Darin Dimitrov Feb 19 '13 at 14:43