Mocking the UrlHelper in MVC

by Administrator 2. Dezember 2011 03:18

This took me some time to find out but it's actually quite easy. I wanted to test a method that calls IsLocalUrl on the UrlHelper class provided by MVC. The bad news is that there does not seem to be a good way to replace the class as a whole, however there is an easy way to get what you need. The following code is done for RhinoMocks but you should easily be able to use it with other mocking frameworks as well:

UrlHelper m_UrlHelper = new UrlHelper( new RequestContext(){HttpContext = m_Mock.PartialMock<HttpContextBase>()});
using( m_Mock.Record() )
{
  m_UrlHelper.RequestContext.HttpContext
     .Expect( context => context.Request.Url )
     .Repeat.Any()
     .Return( new Uri( "http://PC/DevUIWeb" ) );
}

The key takeaway here is, that the url helper itself does not provide it's methods as virtual (thanks guys) and mocking is not possible out of the box. However you can mimic a real context by mocking the actual HttpContext object inside.

Tags: , ,

ASP.NET MVC | C#

Output Caching for Css Files in ASP.NET MVC

by Administrator 31. August 2011 05:13

ASP.NET MVC offers an easy way to implement output caching using an attribute:


[OutputCache( VaryByParam = "pathInfo", Duration = 60 )]
public virtual ActionResult Index( string pathInfo )

What this does is storing an in memory version of the generated output for 60 minutes for the given path info. MVC handles such attributes in a pipeline where each attribute has a defined sort order. Then there is a chance to execute before and after the next action in the pipeline. Unfortunately output caching does not the preserve the content type set. It always emits text/html which breaks when you try to emit something else (in my case CSS).

I found this post on Stack Overflow that pointed me into the right direction. It just defines a content encoding attribute that should run late in the papeline. It is even nice to use this attribute when not running into the caching issue since you can decorate your controller action with the content type it returns. Here is the attribute:


public class ContentTypeAttribute : ActionFilterAttribute
{
  protected const int EXECUTION_ORDER = 1000;

  public string ContentType
  {
     get;
     set;
  }

  public ContentTypeAttribute ()
  {
     Order = EXECUTION_ORDER;
  }

  public override void OnResultExecuted( ResultExecutedContext filterContext )
  {
     if( string.IsNullOrEmpty( ContentType ) )
     {
        throw new InvalidOperationException( "The attribute requires a content type." );
     }

     filterContext.HttpContext.Response.ContentType = ContentType;
  }
}

To use this attribute mark the controller action as following:


[ContentType( ContentType = "text/css" )]
[OutputCache( VaryByParam = "pathInfo", Duration = 60 )]

The only thing I relly changed from the proposed solution is hardcoding the sort order into the attribute since I do not see any reason to make the implementer specify it.

Tags: ,

ASP.NET MVC

About the author

for comments and suggestions contact:

 

Month List