このリンク でアドバイスされているように、コントローラーへの呼び出しにエラーを返そうとしていたので、クライアントは適切なアクションを取ることができます。コントローラは、jquery AJAXを介してjavascriptによって呼び出されます。ステータスをエラーに設定しない場合にのみ、Jsonオブジェクトを取得しています。サンプルコードはこちら
if (response.errors.Length > 0)
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(response);
ステータスコードを設定しない場合、Jsonを取得します。ステータスコードを設定すると、Jsonエラーオブジェクトではなく、ステータスコードが返されます。
Updateajaxのエラーコールバックを処理できるように、ErrorオブジェクトをJSONとして送信したい。
私は解決策を見つけました ここ
MVCのデフォルトの動作をオーバーライドするには、アクションフィルターを作成する必要がありました
ここに私の例外クラスがあります
class ValidationException : ApplicationException
{
public JsonResult exceptionDetails;
public ValidationException(JsonResult exceptionDetails)
{
this.exceptionDetails = exceptionDetails;
}
public ValidationException(string message) : base(message) { }
public ValidationException(string message, Exception inner) : base(message, inner) { }
protected ValidationException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
JSONを初期化するコンストラクターがあることに注意してください。ここにアクションフィルターがあります
public class HandleUIExceptionAttribute : FilterAttribute, IExceptionFilter
{
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.Exception != null)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.Result = ((ValidationException)filterContext.Exception).myJsonError;
}
}
アクションフィルターができたので、フィルター属性でコントローラーを装飾します
[HandleUIException]
public JsonResult UpdateName(string objectToUpdate)
{
var response = myClient.ValidateObject(objectToUpdate);
if (response.errors.Length > 0)
throw new ValidationException(Json(response));
}
エラーがスローされると、IExceptionFilterを実装するアクションフィルターが呼び出され、エラーコールバックでクライアントのJsonが返されます。
私が見つけた最も近いソリューションは、元の実装を拡張し、HttpStatusCodeを指定できる独自のJsonResultを作成することです。
public class JsonHttpStatusResult : JsonResult
{
private readonly HttpStatusCode _httpStatus;
public JsonHttpStatusResult(object data, HttpStatusCode httpStatus)
{
Data = data;
_httpStatus = httpStatus;
}
public override void ExecuteResult(ControllerContext context)
{
context.RequestContext.HttpContext.Response.StatusCode = (int)_httpStatus;
base.ExecuteResult(context);
}
}
これをコントローラーアクションで次のように使用できます。
if(thereWereErrors)
{
var errorModel = new { error = "There was an error" };
return new JsonHttpStatusResult(errorModel, HttpStatusCode.InternalServerError);
}
この問題に対する非常に洗練された解決策があります。web.configを使用してサイトを構成するだけです。
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough"/>
</system.webServer>
リチャード・ガーサイドからの回答に基づいて、ASP.Net Coreバージョンを紹介します
public class JsonErrorResult : JsonResult
{
private readonly HttpStatusCode _statusCode;
public JsonErrorResult(object json) : this(json, HttpStatusCode.InternalServerError)
{
}
public JsonErrorResult(object json, HttpStatusCode statusCode) : base(json)
{
_statusCode = statusCode;
}
public override void ExecuteResult(ActionContext context)
{
context.HttpContext.Response.StatusCode = (int)_statusCode;
base.ExecuteResult(context);
}
public override Task ExecuteResultAsync(ActionContext context)
{
context.HttpContext.Response.StatusCode = (int)_statusCode;
return base.ExecuteResultAsync(context);
}
}
次に、コントローラーで次のように戻ります。
// Set a json object to return. The status code defaults to 500
return new JsonErrorResult(new { message = "Sorry, an internal error occurred."});
// Or you can override the status code
return new JsonErrorResult(new { foo = "bar"}, HttpStatusCode.NotFound);
StatusCodeを設定した後、JSONエラーオブジェクトを自分で返す必要があります。
if (BadRequest)
{
Dictionary<string, object> error = new Dictionary<string, object>();
error.Add("ErrorCode", -1);
error.Add("ErrorMessage", "Something really bad happened");
return Json(error);
}
別の方法は、JsonErrorModel
を使用してそれを設定することです
public class JsonErrorModel
{
public int ErrorCode { get; set;}
public string ErrorMessage { get; set; }
}
public ActionResult SomeMethod()
{
if (BadRequest)
{
var error = new JsonErrorModel
{
ErrorCode = -1,
ErrorMessage = "Something really bad happened"
};
return Json(error);
}
//Return valid response
}
答えを見てください こちら も同様に
「HTTPレベルエラー」(エラーコードの目的)または「アプリケーションレベルエラー」(カスタムJSON応答の目的)のどちらを使用するかを決定する必要があります。
HTTPを使用するほとんどの高レベルオブジェクトは、エラーコードが2xx(成功範囲)以外の値に設定されている場合、応答ストリームを参照しません。あなたの場合、エラーコードを明示的に失敗に設定し(403または500と思います)、XMLHttpオブジェクトに応答の本文を無視させます。
修正するには-クライアント側でエラー状態を処理するか、エラーコードを設定せずにエラー情報付きのJSONを返します(詳細については、Sbossbの返信を参照してください)。
また、ニーズがサラスほど複雑でない場合は、さらに単純なもので逃げることができます。
[MyError]
public JsonResult Error(string objectToUpdate)
{
throw new Exception("ERROR!");
}
public class MyErrorAttribute : FilterAttribute, IExceptionFilter
{
public virtual void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.Exception != null)
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult() { Data = filterContext.Exception.Message };
}
}
}
私のために働いた(そして、私は 別のstackoverflow response から取った)、フラグを設定することです:
Response.TrySkipIisCustomErrors = true;
Jsonにエラーを送信する簡単な方法は、応答オブジェクトのHTTPステータスコードを制御し、カスタムエラーメッセージを設定することです。
コントローラー
public JsonResult Create(MyObject myObject)
{
//AllFine
return Json(new { IsCreated = True, Content = ViewGenerator(myObject));
//Use input may be wrong but nothing crashed
return Json(new { IsCreated = False, Content = ViewGenerator(myObject));
//Error
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return Json(new { IsCreated = false, ErrorMessage = 'My error message');
}
[〜#〜] js [〜#〜]
$.ajax({
type: "POST",
dataType: "json",
url: "MyController/Create",
data: JSON.stringify(myObject),
success: function (result) {
if(result.IsCreated)
{
//... ALL FINE
}
else
{
//... Use input may be wrong but nothing crashed
}
},
error: function (error) {
alert("Error:" + erro.responseJSON.ErrorMessage ); //Error
}
});