3

統合のためだけにプライベートな「ヘルパー」メソッドに引き出された、いくつかのコントローラーアクションに共通するコードがいくつかあります。このメソッドは、いくつかの健全性/セキュリティチェックを実行し、ユーザーを他のアクションにリダイレクトする可能性がありますが、オブジェクトを「取得」することが期待されています。

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を返すことです。

4

5 に答える 5

3

エラーの原因となる実行フローを中断せずに、アクションで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
  }

}
于 2011-02-18T16:45:15.747 に答える
2

これを行う1つの方法は、リダイレクトを処理するための例外フィルターを定義することです。

まず、リダイレクトを表すカスタム例外を作成します。

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();
}

もちろんGetThingy()、try / catch内から呼び出さないようにする必要があります。そうする場合は、例外を再スローするようにしてください。

于 2013-09-16T13:16:24.123 に答える
0

試す:

return RedirectToAction("youraction", "yourcontroller");

それが役に立てば幸い。

于 2011-02-18T16:30:43.380 に答える
0

これはどうですか。

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;
}

ちなみに、IMHOGetThingy(int id)メソッドは別の場所に配置する必要があります。たぶんと同じ場所にsome_call_to_service_layer(id)

于 2011-02-18T16:41:43.163 に答える
0

わかりました、私はそれを理解したと思います。どうやら、あなたはこの種のもののために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;
}

うまく機能し、コードを希望の場所に保持できます。かなり甘い。

于 2011-02-18T17:03:18.240 に答える