web-dev-qa-db-ja.com

MVCコントローラーで例外をスローせずにエラーを$ .ajaxに報告する方法は?

私はコントローラーと定義されたメソッドを持っています...

[HttpPost]
public ActionResult UpdateUser(UserInformation model){

   // Instead of throwing exception
   throw new InvalidOperationException("Something went wrong");


   // I need something like 
   return ExecutionError("Error Message");

   // which should be received as an error to my 
   // $.ajax at client side...

}

例外の問題

  1. SQL接続エラーなどのデバイスまたはネットワークエラーの場合、例外をログに記録する必要があります。
  2. これらのメッセージは、ユーザーに対する検証メッセージのようなものであり、ログに記録することは望ましくありません。
  3. 例外をスローすると、イベントビューアーもあふれます。

クライアント側でエラーが発生するように、カスタムHTTPステータスを$ .ajax呼び出しに報告する簡単な方法が必要ですが、エラーをスローしたくありません。

[〜#〜] update [〜#〜]

クライアントスクリプトが他のデータソースと矛盾するため、クライアントスクリプトを変更できません。

これまでのところ、HttpStatusCodeResultは機能するはずですが、IISが問題の原因となっています。設定したエラーメッセージに関係なく、すべての回答を試みても、デフォルトメッセージのみを受け取ります。

34
Akash Kava

これがHTTPステータスコードの出番です。 Ajaxを使用すると、それに応じてそれらを処理できます。

[HttpPost]
public ActionResult UpdateUser(UserInformation model){
    if (!UserIsAuthorized())
        return new HttpStatusCodeResult(401, "Custom Error Message 1"); // Unauthorized
    if (!model.IsValid)
        return new HttpStatusCodeResult(400, "Custom Error Message 2"); // Bad Request
    // etc.
}

定義済みのステータスコード のリストを次に示します。

48
Dennis Traub

説明

オブジェクトをページに戻し、ajaxコールバックで分析するのはどうですか。

サンプル

[HttpPost]
public ActionResult UpdateUser(UserInformation model)
{
    if (SomethingWentWrong)
        return this.Json(new { success = false, message = "Uuups, something went wrong!" });

    return this.Json(new { success=true, message=string.Empty});
}

jQuery

$.ajax({
  url: "...",
  success: function(data){
    if (!data.success) 
    {
       // do something to show the user something went wrong using data.message
    } else {
       // YES! 
    }
  }
});
9
dknaack

サーバーエラーを返すカスタムステータスコードを使用して、ベースコントローラーにヘルパーメソッドを作成できます。例:

public abstract class MyBaseController : Controller
{
    public EmptyResult ExecutionError(string message)
    {
        Response.StatusCode = 550;
        Response.Write(message);
        return new EmptyResult();
    }
}

必要なときにアクションでこのメソッドを呼び出します。あなたの例では:

[HttpPost]
public ActionResult UpdateUser(UserInformation model){

   // Instead of throwing exception
   // throw new InvalidOperationException("Something went wrong");


   // The thing you need is 
   return ExecutionError("Error Message");

   // which should be received as an error to my 
   // $.ajax at client side...

}

エラー(カスタムコード「550」を含む)は、次のようにクライアント側でグローバルに処理できます。

$(document).ready(function () {
    $.ajaxSetup({
        error: function (x, e) {
            if (x.status == 0) {
                alert('You are offline!!\n Please Check Your Network.');
            } else if (x.status == 404) {
                alert('Requested URL not found.');
/*------>*/ } else if (x.status == 550) { // <----- THIS IS MY CUSTOM ERROR CODE
                alert(x.responseText);
            } else if (x.status == 500) {
                alert('Internel Server Error.');
            } else if (e == 'parsererror') {
                alert('Error.\nParsing JSON Request failed.');
            } else if (e == 'timeout') {
                alert('Request Time out.');
            } else {
                alert('Unknow Error.\n' + x.responseText);
            }
        }
    });
});
4
shizik

これは、JSONとしてajaxリクエストに例外を送信するように記述したクラスです

public class FormatExceptionAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult()
                                        {
                                            ContentType = "application/json",
                                            Data = new
                                                    {
                                                        name = filterContext.Exception.GetType().Name,
                                                        message = filterContext.Exception.Message,
                                                        callstack = filterContext.Exception.StackTrace
                                                    },
                                            JsonRequestBehavior = JsonRequestBehavior.AllowGet
                                        };

                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.StatusCode = 500;
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; 
            }
            else
            {
                base.OnException(filterContext);
            }
        }
    }

次のように、アプリケーションのGlobal.asax.csファイルでMVCに登録されます。

GlobalFilters.Filters.Add(new FormatExceptionAttribute());
2
Jason

私が見つけた最良の方法は次のとおりです。

// Return error status and custom message as 'errorThrown' parameter of ajax request
return new HttpStatusCodeResult(400, "Ajax error test");
1
GP24

BigMikeの投稿に基づいて、これは私がNON MVC/WEBAPI Webプロジェクトで行ったことです。

Response.ContentType = "application/json";
Response.StatusCode = 400;
Response.Write (ex.Message);

それが価値があるもの(そしてBigMikeに感謝!).

1
roblem

この特定のクラスをAjaxエラーに使用します

public class HttpStatusCodeResultWithJson : JsonResult
{
    private int _statusCode;
    private string _description;
    public HttpStatusCodeResultWithJson(int statusCode, string description = null)
    {
        _statusCode = statusCode;
        _description = description;
    }
    public override void ExecuteResult(ControllerContext context)
    {
        var httpContext = context.HttpContext;
        var response = httpContext.Response;
        response.StatusCode = _statusCode;
        response.StatusDescription = _description;
        base.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
        base.ExecuteResult(context);
    }
}

ステータスコードはカスタムHTTPステータスコードであり、グローバルAjaxエラー関数で次のようにテストします。

MyNsp.ErrorAjax = function (xhr, st, str) {
        if (xhr.status == '418') {
            MyNsp.UI.Message("Warning: session expired!");
            return;
        }
        if (xhr.status == "419") {
            MyNsp.UI.Message("Security Token Missing");
            return;
        }
        var msg = 'Error: ' + (str ? str : xhr.statusText);
        MyNsp.UI.Message('Error. - status:' + st + "(" + msg + ")");
        return;
    };
1
BigMike