Skip to content

JonKruger/HttpInterfaces

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HttpInterfaces provides interfaces to wrap HttpContext and other unmockable, abstract base classes that you might use in your controllers and model binders on an ASP.NET MVC project.

For example, in the following code, you would not be able write a unit test for this code because you don't have an actual HttpContext:

public class OrderController
{
	public ActionResult Index()
	{
		Session["foo"] = "bar";
		var productName = Request.Form["Product_3_Name"];
	}
}

You can try to use partial mocks, create derived classes, and implement abstract classes in order to make these things testable, but everyone I know who has tried eventually gets frustrated or runs into something they can't fake out in a test. So just save yourself the trouble and use the interfaces instead.

You get the following interfaces:

ICache - Cache
IHttpApplication - HttpApplication
IHttpApplicationState - HttpApplicationState
IHttpCachePolicy - CachePolicy
IHttpClientCertificate - HttpClientCertificate
IHttpContext - HttpContext
IHttpFileCollection - HttpFileCollection
IHttpModuleCollection - HttpModuleCollection
IHttpRequest - HttpRequest
IHttpResponse - HttpResponse
IHttpServerUtility - HttpServerUtility
IHttpSession - System.Web.SessionState.HttpSessionState
ITraceContext - TraceContext

You can configure a DI container like StructureMap to use the interfaces like this:

ObjectFactory.Initialize(x =>
{
    x.For<IHttpApplication>().Use(
        c => WebContext.Cast(HttpContext.Current.ApplicationInstance));
    x.For<IHttpApplicationState>().Use(
        c => WebContext.Cast(HttpContext.Current.Application));
    x.For<IHttpCachePolicy>().Use(
        c => WebContext.Cast(HttpContext.Current.Response.Cache));
    x.For<IHttpClientCertificate>().Use(
        c => WebContext.Cast(HttpContext.Current.Request.ClientCertificate));
    x.For<IHttpContext>().Use(
        c => WebContext.Cast(HttpContext.Current));
    x.For<IHttpFileCollection>().Use(
        c => WebContext.Cast(HttpContext.Current.Request.Files));
    x.For<IHttpModuleCollection>().Use(
        c => WebContext.Cast(HttpContext.Current.ApplicationInstance.Modules));
    x.For<IHttpRequest>().Use(
        c => WebContext.Cast(HttpContext.Current.Request));
    x.For<IHttpResponse>().Use(
        c => WebContext.Cast(HttpContext.Current.Response));
    x.For<IHttpServerUtility>().Use(
        c => WebContext.Cast(HttpContext.Current.Server));
    x.For<IHttpSession>().Use(
        c => WebContext.Cast(HttpContext.Current.Session));
    x.For<ITraceContext>().Use(
        c => WebContext.Cast(HttpContext.Current.Trace));
}

Now you can take these interfaces into your controllers as constructor parameters:

public class OrderController
{
	private IHttpSession _session;
	private IHttpRequest _request;
	
	public OrderController(IHttpSession session, IHttpRequest request)
	{
		_session = session;
		_request = request;
	}
	
	public ActionResult Index()
	{
		_session["foo"] = "bar";
		var productName = _request.Form["Product_3_Name"];
	}
}

I can easily test these controller methods because I can stub out the interfaces in my tests.

This was originally inspired by this blog post by Phil Haack. In Phil's post, he uses a library that dynamically generates the interfaces. I ran into some problems with the library that did this... it sometimes would throw an exception generating the interface code and I would have to restart IIS. So I spent the 20 minutes that it took to create the interfaces and implement the proxy classes by hand.

Installation

Easiest way to install is to use nuget.

 Install-Package HttpInterfaces

Have fun!

About

Proxy classes for HttpContext and related objects, based on Phil Haack's blog post but without the 3rd party DuckTyping library that was causing massive failures in my production environment.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages