I'm working on an ASP.NET MVC solution that has a number of different menus. The menu to display depends on the role of the currently logged in user.
In MVC 3 I had some custom code to support this scenario, by having a single controller method that would return the right menu. It would do this by deferring the request to the appropriate controller and action depending on the current user.
This code appears to be broken in MVC 4 and I'm looking for help to fix it.
First, I added a TransferResult helper class to perform the redirection:
public class TransferResult : RedirectResult
{
#region Transfer to URL
public TransferResult( string url ) : base( url )
{
}
#endregion
#region Transfer using RouteValues
public TransferResult( object routeValues ) : base( GetRouteUrl( routeValues ) )
{
}
private static string GetRouteUrl( object routeValues )
{
var url = new UrlHelper( new RequestContext( new HttpContextWrapper( HttpContext.Current ), new RouteData() ), RouteTable.Routes );
return url.RouteUrl( routeValues );
}
#endregion
#region Transfer using ActionResult (T4MVC only)
public TransferResult( ActionResult result ) : base( GetRouteUrl( result.GetT4MVCResult() ) )
{
}
private static string GetRouteUrl( IT4MVCActionResult result )
{
var url = new UrlHelper( new RequestContext( new HttpContextWrapper( HttpContext.Current ), new RouteData() ), RouteTable.Routes );
return url.RouteUrl( result.RouteValueDictionary );
}
#endregion
public override void ExecuteResult( ControllerContext context )
{
HttpContext httpContext = HttpContext.Current;
httpContext.RewritePath( Url, false );
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest( HttpContext.Current );
}
}
Second, I modified T4MVC to emit a few controller helper methods, resulting in every controller having this method:
protected TransferResult Transfer( ActionResult result )
{
return new TransferResult( result );
}
This allowed me to have a shared controller action to return a menu, without having to clutter the views with any conditional logic:
public virtual ActionResult Menu()
{
if( Principal.IsInRole( Roles.Administrator ) )
return Transfer( MVC.Admin.Actions.Menu() );
return View( MVC.Home.Views.Partials.Menu );
}
However, the code in ExecuteResult in the TransferResult class does not seem to work with the current preview release of MVC 4. It gives me the following error (pointing to the "httpHandler.ProcessRequest" line):
'HttpContext.SetSessionStateBehavior' can only be invoked before
'HttpApplication.AcquireRequestState' event is raised.
Any idea how to fix this?
PS: I realize that I could achieve the same using a simple HtmlHelper extension, which is what I'm currently using as a workaround. However, I have many other scenarios where this method has allowed me to mix and reuse actions, and I would hate to give up this flexibility when moving to MVC 4.