2008-09-21 4 views
9

aspnet mvc hat den HandleError-Filter, der eine Ansicht zurückgibt, wenn ein Fehler auftritt, aber wenn beim Aufruf einer JsonResult-Aktion ein Fehler auftritt, wie kann ich ein JSON-Objekt zurückgeben, das einen Fehler darstellt?Wie kann JSON von einem HandleError-Filter zurückgegeben werden?

Ich möchte den Code nicht in jede Aktionsmethode einbinden, die ein JsonResult in einem try/catch zurückgibt, um es zu erreichen, ich würde es lieber tun, indem ich ein 'HandleJsonError'-Attribut hinzufüge oder das vorhandene HandleError-Attribut verwende die erforderlichen Maßnahmen.

Antwort

9

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

+0

Ich habe das versucht, aber wenn die HandleJsonErrorAttribute OnException-Methode aufgerufen wird, ist die filterContext.ExceptionHandled-Eigenschaft immer true, wenn es ein HandleErrorAttribute für die Controller-Klasse gibt, zu der die Aktion gehört. Sollten die Aktionsmethoden handleerror Priorität haben und zuerst aufgerufen werden? –

1

Vielleicht könnten Sie Ihr eigenes Attribut erstellen und einen Konstruktorwert haben, der einen Aufzählungswert von View oder Json hat. Unten ist, was ich für ein benutzerdefiniertes Autorisierungsattribut verwende, um zu zeigen, was ich meine. Auf diese Weise antwortet die Authentifizierung bei einer JSON-Anfrage mit einem JSON-Fehler und mit dem gleichen, wenn sie eine Ansicht zurückgibt.

+0

Ich werde versuchen, ein funktionierendes Beispiel zu implementieren. Wenn Sie herausfinden, dass es nicht funktioniert oder eine andere Lösung findet, lassen Sie es mich wissen! – Vyrotek

7

Kurz gesagt, die Art und Weise kann zu gehen, um die HandleErrorAttribute zu verlängern, wie folgt aus:

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 Elmah Logging-Code Zeile, wenn Sie es nicht brauchen. Ich benutze einen meiner Controller, um einen 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 füge einige Ticket Info oben hinzu, können Sie dies ignorieren. Aufgrund der Art und Weise der Filter implementiert ist (der Standard HandleErrorAttributes erweitert) können wir entfernen dann HandleErrorAttribute aus den globalen Filter:

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 es im Grunde ist. Sie können my blog entry für weitere Informationen lesen, aber für die Idee, sollte oben ausreichen.

+2

Das obige funktioniert während der Entwicklung in IISExpress. Damit dies bei der Bereitstellung auf dem echten IIS-Webserver funktioniert, mussten wir 'context.HttpContext.Response.TrySkipIisCustomErrors = true;' hinzufügen, wenn unsere jsonmessage als IIS-Otherwize erstellt wird, überschreibt die Fehlermeldung und zeigt ihre Standard-Statuscode 500-Seite an – mortb

Verwandte Themen