.NET MVC:如何在辅助方法中重定向响应

我有一些代码,这些代码对于我的一些控制器操作是常见的,这些操作被引入私有“帮助器”方法,仅用于整合。该方法应该为我“获取”一个对象,尽管它执行一些健全/安全检查,并可能将用户重定向到其他操作。
private Thingy GetThingy(int id)
{
    var thingy = some_call_to_service_layer(id);

    if( null == thingy )
        Response.Redirect( anotherActionUrl );

    // ... many more checks, all more complex than a null check

    return thingy;
}

public ActionResult ActionOne(int id)
{
    var thingy = GetThingy(id);
    // do more stuff
    return View();
}

// ... n more actions

public ActionResult ActionM(int id)
{
    var thingy = GetThingy(id);
    // do more stuff
    return View();
}
这个功能正常,但Elmah会通知我一个异常:
System.Web.HttpException: Cannot redirect after HTTP headers have been sent.
所以,我的问题是:有没有更正确的方法来做我想做的事情?基本上,我想要的是使当前操作停止处理,而是返回RedirectToRouteResult。     
已邀请:
您不能在操作中调用Response.Redirect()而不会中断导致错误的执行流程。相反,你可以返回一个
RedirectToRouteResult
对象或一个
RedirectResult
对象。在你的行动中
return Redirect("/path");
//or
return RedirectToAction("actionname");
在你的情况下,你想要返回一个
Thingy
对象,你需要分离出逻辑。您可以执行以下操作(我假设您要重定向到不同的操作,否则Oenning的代码将起作用)
public ActionResult Get(int id) {

  var thingy = GetThingy(id);

  var result = checkThingy(thingy);
  if (result != null) {
    return result;
  }

  //continue...
}

[NonAction]
private ActionResult CheckThingy(Thingy thingy) {

  //run check on thingy
  //return new RedirectResult("path");

  //run another check
  //new RedirectResult("different/path");

  return null;
}
更新您可以将此代码放在扩展方法或基本Controller类中
public static class ThingyExtensions {

  public static ActionResult Check(this Thingy thingy) {
    //run checks here
  }

}
    
一种方法是定义一个异常过滤器来为您处理重定向。 首先,创建一个自定义异常来表示重定向:
public class RedirectException : Exception {

    private readonly string _url;

    public RedirectException(string url) {
        _url = url;
    }

    public string Url { get { return _url; }}

}
然后,定义您的异常过滤器:
public class RedirectExceptionAttribute : FilterAttribute, IExceptionFilter {
    public void OnException(ExceptionContext filterContext) {

        if (filterContext.ExceptionHandled) return;
        if (filterContext.Exception.GetType() != typeof(RedirectException)) return;

        filterContext.Result = new RedirectResult(((RedirectException)filterContext.Exception).Url);
        filterContext.ExceptionHandled = true;
    }
}
全局注册新的异常过滤器,以便它适用于所有控制器操作(如果这是您想要的):
// in FilterConfig.cs (MVC 4.0)
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
    filters.Add(new RedirectExceptionAttribute());
}
现在,无论您想要重定向,只需抛出RedirectException:
private Thingy GetThingy(int id)
{
    var thingy = some_call_to_service_layer(id);

    if( null == thingy )
        throw new RedirectException( anotherActionUrl );

    // ... many more checks, all more complex than a null check

    return thingy;
}

public ActionResult ActionOne(int id)
{
    var thingy = GetThingy(id);
    // do more stuff
    return View();
}

// ... n more actions

public ActionResult ActionM(int id)
{
    var thingy = GetThingy(id);
    // do more stuff
    return View();
}
当然,您需要确保不要在try / catch中调用
GetThingy()
,或者如果您这样做,请确保重新抛出异常。     
尝试:
return RedirectToAction("youraction", "yourcontroller");
希望能帮助到你。     
那这个呢。
public ActionResult ActionOne(int id)
{
    var thingy = GetThingy(id);
    if (thingy == null)
        return RedirectToAction("action", "controller");
    // do more stuff
    return View();
}

private Thingy GetThingy(int id)
{
    var thingy = some_call_to_service_layer(id);

    if( null == thingy )
        return null;

    // ... many more checks, all more complex than a null check

    return thingy;
}
顺便说一句,恕我直言,
GetThingy(int id)
方法应放在其他地方。也许和ѭ16在同一个地方。     
好吧,我想我弄明白了。显然,你可以随意触发ActionResult的执行。所以辅助方法变为:
private Thingy GetThingy(int id)
{
    var thingy = some_call_to_service_layer(id);

    if( null == thingy )
        RedirectToAction("myAction").ExecuteResult(ControllerContext);

    // ... many more checks, all more complex than a null check

    return thingy;
}
很好地工作,并允许我将代码保持在我想要的位置。很甜蜜。     

要回复问题请先登录注册