views:

54

answers:

2

I've used the PermanentRedirectResult from here to perform 301 redirects in ASP.NET MVC 1. Since upgrading to 2.0, the 301 response is no longer sent. Instead, a 200 response containing just the class name is sent.

Setting a breakpoint indicates that the ExecuteResult method on PermanentRedirectResult is never called. Apparently the framework is just calling ToString() on the result instead of executing it.

Has anyone else seen this? Is this a deliberate change in 2.0, and if so what do I now need to do to use a custom ActionResult?

+1  A: 

Reworked a bit from Steve Sanderson's Pro ASP.NET MVC 2 Framework which I highly recommend you buy. There's no better resource.

public class HomeController : Controller
{
  public ActionResult Index()
  {
    return RedirectToAction("Other").MakePermanent();
  }

  public ActionResult Other()
  {
    return View();
  }
}

public static class RedirectExtensions
{
  public static PermRedirectToRouteResult MakePermanent(this RedirectToRouteResult redirect)
  {
    return new PermRedirectToRouteResult(redirect);
  }

  public class PermRedirectToRouteResult : ActionResult
  {
    public RedirectToRouteResult Redirect { get; private set; }
    public PermRedirectToRouteResult(RedirectToRouteResult redirect)
    {
      this.Redirect = redirect;
    }
    public override void ExecuteResult(ControllerContext context)
    {
      Redirect.ExecuteResult(context);
      context.HttpContext.Response.StatusCode = 301;
    }
  }
}
Tyler Jensen
My problem turned out to be with project references rather than the actual code of the ActionResult, but have an accept and an upvote because the MakePermanent extension method is a nicer way to handle 301s, and testing this code in my project made me realise what was wrong with my existing PermanentRedirectResult.
stevemegson
A: 

It turns out that the project containing the PermanentRedirectResult class still referenced the ASP.NET MVC 1.0 assembly, although the web site had been updated to reference 2.0. The framework tests the return value of the action method to see if it's an ActionResult or something else that should be wrapped in a ContentResult like this...

return ((actionReturnValue as ActionResult) ??
  new ContentResult {
    Content = Convert.ToString(actionReturnValue, CultureInfo.InvariantCulture)
  });

...and (actionReturnValue as ActionResult) is null because my PermanentRedirectResult extends the wrong ActionResult, the one in the 1.0 assembly rather than the one in the 2.0 assembly.

Updating the reference so that PermanentRedirectResult is a 2.0 ActionResult fixed the problem.

stevemegson