J'ai un contrôleur et une méthode telle que définie ...
[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...
}
Problèmes d'exceptions
Il me faut un moyen simple de signaler un statut http personnalisé à mon appel $ .ajax afin qu’il en résulte une erreur côté client, mais je ne souhaite pas en générer une.
METTRE À JOUR
Je ne peux pas modifier le script client car il devient incompatible avec les autres sources de données.
Jusqu'à présent, HttpStatusCodeResult devrait fonctionner, mais c'est IIS qui est à l'origine du problème ici. Peu importe le message d'erreur que j'ai défini, j'ai essayé toutes les réponses, je ne reçois toujours que le message par défaut.
C’est là que les codes d’état HTTP entrent en jeu. Avec Ajax, vous pourrez les gérer en conséquence.
[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.
}
Voici une liste des codes d’état définis .
Pourquoi ne pas retourner un objet sur votre page et l’analyser dans votre rappel 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!
}
}
});
Vous pouvez créer une méthode d'assistance dans un contrôleur de base qui renverra une erreur de serveur, mais avec votre code d'état personnalisé. Exemple:
public abstract class MyBaseController : Controller
{
public EmptyResult ExecutionError(string message)
{
Response.StatusCode = 550;
Response.Write(message);
return new EmptyResult();
}
}
Vous appellerez cette méthode dans vos actions si nécessaire. Dans votre exemple:
[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...
}
Les erreurs (y compris le code personnalisé '550') peuvent être gérées globalement côté client de la manière suivante:
$(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);
}
}
});
});
C’est une classe où j’ai écrit les exceptions d’envoi aux requêtes ajax en JSON
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);
}
}
}
Il est enregistré avec MVC dans le fichier Global.asax.cs de votre application, comme suit:
GlobalFilters.Filters.Add(new FormatExceptionAttribute());
Le meilleur moyen que j'ai trouvé est le suivant:
// Return error status and custom message as 'errorThrown' parameter of ajax request
return new HttpStatusCodeResult(400, "Ajax error test");
D'après ce que BigMike a publié, c'est ce que j'ai fait dans mon projet Web NON MVC/Web API.
Response.ContentType = "application/json";
Response.StatusCode = 400;
Response.Write (ex.Message);
Pour ce que cela vaut (et merci BigMike!) Cela a fonctionné parfaitement.
J'utilise cette classe particulière pour les erreurs 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);
}
}
Le code d'état est un code d'état HTTP personnalisé et, dans une fonction d'erreur Ajax globale, je le teste comme suit:
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;
};