116 votes

Gestion des erreurs de Ajax ASP.NET MVC

Comment gérer les exceptions émises dans un contrôleur lorsque jquery ajax appelle une action?

Par exemple, je voudrais un code javascript global qui soit exécuté sur tout type d’exception de serveur lors d’un appel ajax qui affiche le message d’exception en mode débogage ou tout simplement un message d’erreur normal.

Du côté du client, j'appellerai une fonction sur l'erreur ajax.

Sur le serveur, est-ce que je dois écrire un filtre d'action personnalisé?

161voto

Darin Dimitrov Points 528142

Si le serveur envoie un code de statut différent de 200, l'erreur de rappel est exécutée:

$.ajax({
    url: '/foo',
    success: function(result) {
        alert('yeap');
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert('oops, something bad happened');
    }
});

et pour vous inscrire mondiale gestionnaire d'erreur que vous pourriez utiliser l' $.ajaxSetup() méthode:

$.ajaxSetup({
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert('oops, something bad happened');
    }
});

Une autre façon est d'utiliser JSON. Donc, vous pourriez écrire une action personnalisée filtre sur le serveur, qui attrape les exceptions et les transforme en réponse JSON:

public class MyErrorHandlerAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        filterContext.ExceptionHandled = true;
        filterContext.Result = new JsonResult
        {
            Data = new { success = false, error = filterContext.Exception.ToString() },
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    }
}

puis les décorer votre contrôleur de l'action avec cet attribut:

[MyErrorHandler]
public ActionResult Foo(string id)
{
    if (string.IsNullOrEmpty(id))
    {
        throw new Exception("oh no");
    }
    return Json(new { success = true });
}

et enfin l'invoquer:

$.getJSON('/home/foo', { id: null }, function (result) {
    if (!result.success) {
        alert(result.error);
    } else {
        // handle the success
    }
});

72voto

Arash Points 311

Après avoir googlé, j'écris une simple remise d'exception basée sur le filtre d'action MVC:

 public class HandleExceptionAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
        {
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new
                {
                    filterContext.Exception.Message,
                    filterContext.Exception.StackTrace
                }
            };
            filterContext.ExceptionHandled = true;
        }
        else
        {
            base.OnException(filterContext);
        }
    }
}
 

et écrivez dans global.ascx:

  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 {
      filters.Add(new HandleExceptionAttribute());
 }
 

puis écrivez ce script sur la mise en page ou la page maître:

 <script type="text/javascript">
      $(document).ajaxError(function (e, jqxhr, settings, exception) {
                       e.stopPropagation();
                       if (jqxhr != null)
                           alert(jqxhr.responseText);
                     });
</script>
 

Enfin, vous devez activer l'erreur personnalisée. et puis en profiter :)

4voto

Daniel Silva Points 41

J'ai fait une rapide solution car j'étais à court de temps et il a fonctionné. Même si je pense que la meilleure option est d'utiliser un Filtre d'Exception, peut-être que ma solution peut aider dans les cas qu'une solution simple est nécessaire.

Je n'ai la suite. Dans la méthode de contrôleur j'ai renvoyé un JsonResult avec une propriété "Succès" à l'intérieur des Données:

    [HttpPut]
    public JsonResult UpdateEmployeeConfig(EmployeConfig employeToSave) 
    {
        if (!ModelState.IsValid)
        {
            return new JsonResult
            {
                Data = new { ErrorMessage = "Model is not valid", Success = false },
                ContentEncoding = System.Text.Encoding.UTF8,
                JsonRequestBehavior = JsonRequestBehavior.DenyGet
            };
        }
        try
        {
            MyDbContext db = new MyDbContext();

            db.Entry(employeToSave).State = EntityState.Modified;
            db.SaveChanges();

            DTO.EmployeConfig user = (DTO.EmployeConfig)Session["EmployeLoggin"];

            if (employeToSave.Id == user.Id)
            {
                user.Company = employeToSave.Company;
                user.Language = employeToSave.Language;
                user.Money = employeToSave.Money;
                user.CostCenter = employeToSave.CostCenter;

                Session["EmployeLoggin"] = user;
            }
        }
        catch (Exception ex) 
        {
            return new JsonResult
            {
                Data = new { ErrorMessage = ex.Message, Success = false },
                ContentEncoding = System.Text.Encoding.UTF8,
                JsonRequestBehavior = JsonRequestBehavior.DenyGet
            };
        }

        return new JsonResult() { Data = new { Success = true }, };
    }

Plus tard dans l'appel ajax j'ai simplement demandé à cette propriété pour savoir si j'avais une exception:

$.ajax({
    url: 'UpdateEmployeeConfig',
    type: 'PUT',
    data: JSON.stringify(EmployeConfig),
    contentType: "application/json;charset=utf-8",
    success: function (data) {
        if (data.Success) {
            //This is for the example. Please do something prettier for the user, :)
            alert('All was really ok');                                           
        }
        else {
            alert('Oups.. we had errors: ' + data.ErrorMessage);
        }
    },
    error: function (request, status, error) {
       alert('oh, errors here. The call to the server is not working.')
    }
});

Espérons que cette aide. Heureux de code! :P

0voto

Brian Ball Points 6468

Pour gérer les erreurs des appels ajax côté client, vous affectez une fonction à l'option error de l'appel ajax.

Pour définir une valeur par défaut globale, vous pouvez utiliser la fonction décrite ici: http://api.jquery.com/jQuery.ajaxSetup .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X