7

通常のページ読み込みエラーの場合、ErrorビューとHandleErrorInfoモデルを使用して例外の詳細をユーザーに報告できます。MVCでAjax呼び出されたPartialViewメソッドからエラーが報告される

Json結果の誤りを期待ajax呼び出しが、私は明示的にエラーを処理し、クライアントに詳細を渡すことができる場合:だから、私の問題は、私はエラーの詳細を報告する方法を参照することはできません

public JsonResult Whatever() 
{ 
    try 
    { 
     DoSomething(); 
     return Json(new { status = "OK" }); 
    } 
    catch (Exception e) 
    { 
     return Json(new { status = "Error", message = e.Message }); 
    } 
} 

Ajax呼び出しから部分的なビューを返すアクションへの呼び出し。

$.ajax({ 
    url: 'whatever/trevor', 
    error: function (jqXHR, status, error) { 
     alert('An error occured: ' + error); 
    }, 
    success: function (html) { 
     $container.html(html); 
    } 
}); 

これは、クライアントには役立たないHttpエラーコード(内部サーバーエラーなど)のみを報告します。成功したPartialView(html)の結果であるまたはのいずれかをエラーメッセージに渡すための巧妙なトリックがありますか?

ViewResultからhtmlを明示的に評価し、Jsonオブジェクトの一部として返すと、状態が悪すぎるようです。このシナリオを処理するための確立されたパターンはありますか?

答えて

14

コントローラのアクション:

public ActionResult Foo() 
{ 
    // Obviously DoSomething could throw but if we start 
    // trying and catching on every single thing that could throw 
    // our controller actions will resemble some horrible plumbing code more 
    // than what they normally should resemble: a.k.a being slim and focus on 
    // what really matters which is fetch a model and pass to the view 

    // Here you could return any type of view you like: JSON, HTML, XML, CSV, PDF, ... 

    var model = DoSomething(); 
    return PartialView(model); 
} 

その後、我々は我々のアプリケーションのためのグローバルエラーハンドラを定義します。ここでは

protected void Application_Error(object sender, EventArgs e) 
{ 
    var exception = Server.GetLastError(); 
    var httpException = exception as HttpException; 
    Response.Clear(); 
    Server.ClearError(); 

    if (new HttpRequestWrapper(Request).IsAjaxRequest()) 
    { 
     // Some error occurred during the execution of the request and 
     // the client made an AJAX request so let's return the error 
     // message as a JSON object but we could really return any JSON structure 
     // we would like here 

     Response.StatusCode = 500; 
     Response.ContentType = "application/json"; 
     Response.Write(new JavaScriptSerializer().Serialize(new 
     { 
      errorMessage = exception.Message 
     })); 
     return; 
    } 

    // Here we do standard error handling as shown in this answer: 
    // http://stackoverflow.com/q/5229581/29407 

    var routeData = new RouteData(); 
    routeData.Values["controller"] = "Errors"; 
    routeData.Values["action"] = "General"; 
    routeData.Values["exception"] = exception; 
    Response.StatusCode = 500; 
    if (httpException != null) 
    { 
     Response.StatusCode = httpException.GetHttpCode(); 
     switch (Response.StatusCode) 
     { 
      case 404: 
       routeData.Values["action"] = "Http404"; 
       break; 
      case 500: 
       routeData.Values["action"] = "Http500"; 
       break; 
     } 
    } 

    IController errorsController = new ErrorsController(); 
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData); 
    errorsController.Execute(rc); 
} 

は、グローバルエラーハンドラで使用ErrorsControllerは次のようになります方法です。おそらく、我々は404と500の行動のためのいくつかのカスタムビューを定義することができます。

public class ErrorsController : Controller 
{ 
    public ActionResult Http404() 
    { 
     return Content("Oops 404"); 
    } 

    public ActionResult Http500() 
    { 
     return Content("500, something very bad happened"); 
    } 
} 

我々はすべてのAJAX要求のため、このエラー処理コードを繰り返す必要がないように、その後、我々はすべてのAJAXエラーをglobal error handlerのためにサブスクライブでしたが、我々が望んでいたならば、我々はそれを繰り返すことができます:

$('body').ajaxError(function (evt, jqXHR) { 
    var error = $.parseJSON(jqXHR.responseText); 
    alert('An error occured: ' + error.errorMessage); 
}); 

そして最後に、我々はこのような場合には部分的なHTMLを返すことを願っていますコントローラのアクションにAJAX要求を発射:

$.ajax({ 
    url: 'whatever/trevor', 
    success: function (html) { 
     $container.html(html); 
    } 
}); 
+1

ダーリンにAjaxAuthorizeAttributeを見てください。私はここでいくつかの点を十分に理解していませんでしたが、グローバルフィルタに登録されたajaxフィルタを使って、同様のことを少し簡単に実現できることを理解しました。それはうまく動作しているようだ。ありがとうございました。 – fearofawhackplanet

+0

上記のコードを使用して404をトラップしてカスタムページを表示している場合は、おそらくResponse.TrySkipIisCustomErrors = true(.net 3.5以降は私が信じる)を追加したい場合は –

+0

魅力的な作品 – Dilip

関連する問題