12 Stimmen

Wie kann man JSON von einem HandleError-Filter zurückgeben?

Aspnet mvc hat den HandleError-Filter, der eine Ansicht zurückgibt, wenn ein Fehler auftritt, aber wenn ein Fehler beim Aufrufen einer JsonResult-Aktion auftritt, wie kann ich ein JSON-Objekt zurückgeben, das einen Fehler darstellt?

Ich möchte nicht den Code in jeder Action-Methode, die ein JsonResult in einem Try/Catch zurückgibt, um es zu erreichen wickeln, würde ich lieber tun es durch Hinzufügen eines "HandleJsonError"-Attributs oder mit dem vorhandenen HandleError-Attribut zu den erforderlichen Action-Methoden.

10voto

Haacked Punkte 56079

Werfen Sie einen Blick auf die MVC-Implementierung von HandleErrorAttribute. Sie gibt ein ViewResult zurück. Sie könnten Ihre eigene Version (HandleJsonErrorAttribute) schreiben, die ein JsonResult zurückgibt.

8voto

Kurz gesagt, kann der Weg zu gehen, um die HandleErrorAttribute, wie folgt zu erweitern:

public class OncHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        // Elmah-Log only handled exceptions
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);

        if (context.HttpContext.Request.IsAjaxRequest())
        {
            // if request was an Ajax request, respond with json with Error field
            var jsonResult = new ErrorController { ControllerContext = context }.GetJsonError(context.Exception);
            jsonResult.ExecuteResult(context);
            context.ExceptionHandled = true;
        }
        else
        {
            // if not an ajax request, continue with logic implemented by MVC -> html error page
            base.OnException(context);
        }
    }
}

Entfernen Sie die Elmah-Logging-Codezeile, wenn Sie sie nicht benötigen. Ich verwende einen meiner Controller, um ein Json basierend auf einem Fehler und Kontext zurückzugeben. Hier ist das Beispiel:

    public class ErrorController : Controller
{
    public ActionResult GetJsonError(Exception ex)
    {
        var ticketId = Guid.NewGuid(); // Lets issue a ticket to show the user and have in the log

        Request.ServerVariables["TTicketID"] = ticketId.ToString(); // Elmah will show this in a nice table

        ErrorSignal.FromCurrentContext().Raise(ex); //ELMAH Signaling

        ex.Data.Add("TTicketID", ticketId.ToString()); // Trying to see where this one gets in Elmah

        return Json(new { Error = String.Format("Support ticket: {0}\r\n Error: {1}", ticketId, ex.ToString()) }, JsonRequestBehavior.AllowGet);
    }

Ich habe oben einige Ticket-Informationen hinzugefügt, die Sie ignorieren können. Aufgrund der Art und Weise, wie der Filter implementiert ist (erweitert die Standard-HandleErrorAttributes) können wir dann HandleErrorAttribute aus den globalen Filtern entfernen:

    public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new GlobalAuthorise());
        filters.Add(new OncHandleErrorAttribute());
        //filters.Add(new HandleErrorAttribute());
    }

Das ist es im Grunde. Sie können lesen mein Blogeintrag für detailliertere Informationen, aber für die Idee sollte das oben Gesagte genügen.

1voto

Vyrotek Punkte 5226

Vielleicht könnten Sie Ihr eigenes Attribut erstellen und einen Konstruktorwert haben, der einen Enum-Wert von View oder Json annimmt. Nachfolgend sehen Sie, was ich für ein benutzerdefiniertes Autorisierungsattribut verwende, um zu zeigen, was ich meine. Auf diese Weise, wenn die Authentifizierung auf eine Json-Anforderung fehlschlägt, antwortet es mit einem Json-Fehler und das gleiche mit, wenn es eine Ansicht zurückgibt.

   public enum ActionResultTypes
   {
       View,
       Json
   }

    public sealed class AuthorizationRequiredAttribute : ActionFilterAttribute, IAuthorizationFilter
    {
        public ActionResultTypes ActionResultType { get; set; }

        public AuthorizationRequiredAttribute(ActionResultTypes actionResultType)
        {
            this.ActionResultType = ActionResultType;
        }
    }

    //And used like
    [AuthorizationRequired(ActionResultTypes.View)]
    public ActionResult About()
    {
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X