.Net MVC output caching by cookie value

A way to control caching provided by ASP.Net is to use a cookie as a parameter. The following example shows how to do this:

1) Create the following method in global.asax

public override string GetVaryByCustomString(HttpContext context, string arg)
{
     if (arg.ToLower() == "cookieuser")
     {
        var cookie = context.Request.Cookies["Your cookie name here"];

        if (cookie != null) { 
           return cookie.Value;
        }
     }
     return base.GetVaryByCustomString(context, arg);
}

2) Add a cache section to web.config

<caching>
  <outputCacheSettings>
      <outputCacheProfiles>
         <add name="CacheOnServer" duration="3600" varyByParam="none" varyByCustom="CookieUser" location="Server" varyByContentEncoding="true" enabled="true" />
         <add name="CacheOnClient" duration="3600" varyByParam="none" varyByCustom="CookieUser" location="Client" varyByContentEncoding="true" enabled="true" />
      </outputCacheProfiles>
  </outputCacheSettings>
</caching>     

3) Decorate the controller

[OutputCache(CacheProfile = "CacheOnServer")]
public ActionResult SomeAction()
{
..
}

.Net MVC testing controller HTTPContext

Here’s a way to test for HTTPContext in a MVC controller:

[Test]
public void TestController_HasContext_ContextNotNull()
{
   var controller = new TestController();

   var server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
   var response = new Mock<HttpResponseBase>(MockBehavior.Strict);

   var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
   request.Setup(r => r.UserHostAddress).Returns("127.0.0.1");

   var session = new Mock<HttpSessionStateBase>();
   session.Setup(s => s.SessionID).Returns(Guid.NewGuid().ToString());

   var context = new Mock<HttpContextBase>();
   context.SetupGet(c => c.Request).Returns(request.Object);
   context.SetupGet(c => c.Response).Returns(response.Object);
   context.SetupGet(c => c.Server).Returns(server.Object);
   context.SetupGet(c => c.Session).Returns(session.Object);

   controller.ControllerContext = new ControllerContext(context.Object,
                    new RouteData(), controller);

   Assert.IsNotNull(controller.HttpContext);
}

.Net MVC Unit testing a child action

A quick demo of how to unit test a child action in with NUnit/MVC:

The controller action

[ChildActionOnly]
public ActionResult ChildActionTest(string category)
{
   var result = new ChildActionModel {ChildProp = category + " This is a child action string."};
   return View("~/Views/Test/ChildActionTest.cshtml", result);
}

The test

[Test]
public void TestController_ChildActionTest_ChildView()
{
   const string testCategory = "TestCategory";
   const string expectedViewName = "~/Views/Test/ChildActionTest.cshtml";

   var controller = new TestController();
   var result = controller.ChildActionTest(testCategory) as ViewResult;

   Assert.IsNotNull(result, "Should have returned a ViewResult");
   Assert.AreEqual(expectedViewName, result.ViewName, "View name should have been {0}",    expectedViewName);
}

.Net MVC C# HTTP Context

There is more than one way to get hold of the HTTP context in a controller:

    // Current via Controller context
    var ctr = ControllerContext;
    var contextBase = ctr.HttpContext.Request;

    // Get the request base
    var httpRequestBase = new HttpRequestWrapper(System.Web.HttpContext.Current.Request);

It’s going to be easier to unit test your code if you use ControllerContext.