【问题标题】:Correct Controller code for a 301 Redirect301 重定向的正确控制器代码
【发布时间】:2010-12-14 04:38:23
【问题描述】:

我正在从静态网站设计一个新的动态网站。我已经对路线进行了排序,但我对我的 Action 方法有疑问。

下面是代码,但是在测试和查看 Firebug 报告的标头时,如果我取出 Response.End,我假设这是一个 302 重定向,因为我设置了 301,但随后调用了另一个操作,使其成为 302,但如果我输入 Response.End 我会得到 301。

我猜测添加 Response.RedirectLocation 实际上是在执行 301 重定向,因此我是否应该将返回值更改为 EmptyResult 或 null,即使该行代码永远不会被执行以便应用程序编译?

public ActionResult MoveOld(string id)
{
    string pagename = String.Empty;

    if(id == "2")
    {
      pagename = WebPage.SingleOrDefault(x => x.ID == 5).URL;
    }

    Response.StatusCode = 301;
    Response.StatusDescription = "301 Moved Permanently";
    Response.RedirectLocation = pagename;
    Response.End();

    return RedirectToAction("Details", new { pageName = pagename });
}

【问题讨论】:

  • 正如我的回答中的 cmets 所述,您实际上在这里执行了两个 ActionResults。 301 重定向本身就是一个 ActionResult,然后您将在发送响应之后用另一个 AFTER 跟进它。

标签: asp.net asp.net-mvc asp.net-mvc-routing


【解决方案1】:

我赞同 Levi's cmets。这不是控制器的工作。我倾向于将this 自定义ActionResult 用于301。下面是一个有更多选项的修改版本。

对于 ASP.NET MVC v2+,使用RedirectResult

public class PermanentRedirectResult : ActionResult
{
  public string Url { get; set; }

  public PermanentRedirectResult(string url)
  {
    Url = url;
  }

  public PermanentRedirectResult(RequestContext context, string actionName, string controllerName)
  {
    UrlHelper urlHelper = new UrlHelper(context);
    string url = urlHelper.Action(actionName, controllerName);

    Url = url;
  }

  public PermanentRedirectResult(RequestContext context, string actionName, string controllerName, object values)
  {
    UrlHelper urlHelper = new UrlHelper(context);
    string url = urlHelper.Action(actionName, controllerName, values);

    Url = url;
  }

  public PermanentRedirectResult(RequestContext context, string actionName, string controllerName, RouteValueDictionary values)
  {
    UrlHelper urlHelper = new UrlHelper(context);
    string url = urlHelper.Action(actionName, controllerName, values);

    Url = url;
  }

  public override void ExecuteResult(ControllerContext context)
  {
    if (context == null)
    {
      throw new ArgumentNullException("context");
    }
    context.HttpContext.Response.StatusCode = 301;
    context.HttpContext.Response.RedirectLocation = Url;
    context.HttpContext.Response.End();
  }
}

在动作中的使用

//Just passing a url that is already known
return new PermanentRedirectResult(url);

//*or*

//Redirect to a different controller/action
return new PermanentRedirectResult(ControllerContext.RequestContext, "ActionName", "ControllerName");

【讨论】:

  • 谢谢,但就像 Levi 所说的那样,调用 Response.End 会引发异常,这有效吗?
  • 如果不执行你的代码,我猜这个错误类似于Cannot redirect after HTTP headers have been sent。那是因为您正在发送响应,然后在您发送响应后重定向用户。 Response.End(); 应该是你做的最后一件事。
  • 这是因为在我给您的代码示例中,PermanentRedirectResult IS 是 ActionResult。实际上,在您的代码中,您有两个 ActionResult。
  • 我意识到我的代码调用了它两次我只是在质疑你的例子中的 Response.End 。您是否需要调用它,因为我相信设置标题会满足要求。我只是想知道如果它抛出异常是否需要它
  • 我不认为 Levi 指的是我的示例,但是是的,它是发送缓冲内容所必需的。我不知道如果你删除它会发生什么。
【解决方案2】:

从 MVC 2.0 开始,这个“RedirectResult”有一个内置的操作结果类。有关更多信息,请参阅此帖子 - MVC RedirectResult

【讨论】:

    【解决方案3】:

    控制器不应负责设置 301 和重定向位置。此逻辑应封装在 ActionResult 中,并且控制器应返回该 ActionResult 的实例。请记住,方法 Response.End() 不会返回(它会引发异常);它后面的行将不会执行。

    【讨论】:

      【解决方案4】:

      【讨论】:

        猜你喜欢
        • 2010-12-23
        • 1970-01-01
        • 2018-04-12
        • 2011-07-03
        • 2016-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-25
        相关资源
        最近更新 更多