0

Так что я недавно построил в ExceptionFilter, который обрабатывает все ошибки, кроме Api Errors. ExceptionFilter выглядит следующим образом:Application_Error и ExceptionFilter

public class ExceptionAttribute : IExceptionFilter 
{ 

    /// <summary> 
    /// Handles any exception 
    /// </summary> 
    /// <param name="filterContext">The current context</param> 
    public void OnException(ExceptionContext filterContext) 
    { 

     // If our exception has been handled, exit the function 
     if (filterContext.ExceptionHandled) 
      return; 

     // If our exception is not an ApiException 
     if (!(filterContext.Exception is ApiException)) 
     { 

      // Set our base status code 
      var statusCode = (int)HttpStatusCode.InternalServerError; 

      // If our exception is an http exception 
      if (filterContext.Exception is HttpException) 
      { 

       // Cast our exception as an HttpException 
       var exception = (HttpException)filterContext.Exception; 

       // Get our real status code 
       statusCode = exception.GetHttpCode(); 
      } 

      // Set our context result 
      var result = CreateActionResult(filterContext, statusCode); 

      // Set our handled property to true 
      filterContext.ExceptionHandled = true; 
     } 
    } 

    /// <summary> 
    /// Creats an action result from the status code 
    /// </summary> 
    /// <param name="filterContext">The current context</param> 
    /// <param name="statusCode">The status code of the error</param> 
    /// <returns></returns> 
    protected virtual ActionResult CreateActionResult(ExceptionContext filterContext, int statusCode) 
    { 

     // Create our context 
     var context = new ControllerContext(filterContext.RequestContext, filterContext.Controller); 
     var statusCodeName = ((HttpStatusCode)statusCode).ToString(); 

     // Create our route 
     var controller = (string)filterContext.RouteData.Values["controller"]; 
     var action = (string)filterContext.RouteData.Values["action"]; 
     var model = new HandleErrorInfo(filterContext.Exception, controller, action); 

     // Create our result 
     var view = SelectFirstView(context, string.Format("~/Views/Error/{0}.cshtml", statusCodeName), "~/Views/Error/Index.cshtml", statusCodeName); 
     var result = new ViewResult { ViewName = view, ViewData = new ViewDataDictionary<HandleErrorInfo>(model) }; 

     // Return our result 
     return result; 
    } 

    /// <summary> 
    /// Gets the first view name that matches the supplied names 
    /// </summary> 
    /// <param name="context">The current context</param> 
    /// <param name="viewNames">A list of view names</param> 
    /// <returns></returns> 
    protected string SelectFirstView(ControllerContext context, params string[] viewNames) 
    { 
     return viewNames.First(view => ViewExists(context, view)); 
    } 

    /// <summary> 
    /// Checks to see if a view exists 
    /// </summary> 
    /// <param name="context">The current context</param> 
    /// <param name="name">The name of the view to check</param> 
    /// <returns></returns> 
    protected bool ViewExists(ControllerContext context, string name) 
    { 
     var result = ViewEngines.Engines.FindView(context, name, null); 

     return result.View != null; 
    } 
} 

Как вы можете видеть, если ошибка неApiException я маршрут пользователя к контроллеру ошибки. ApiException - это просто ошибка, которая возникает, когда я вызываю вызов API из MVC. Когда происходят эти ошибки, я хотел бы вернуть ошибку в качестве JSON обратно клиенту, чтобы JavaScript мог справиться с этим.

Я думал, не обрабатывает ошибки будет делать это, но вместо этого он генерирует ошибку сервера (хотя и с ошибкой JSON в нем) как так:

Server Error in '/' Application.

{"message":"validateMove validation failure:\r\nThe item is despatched and cannot be moved"}

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: SapphirePlus.Web.ApiException: {"message":"validateMove validation failure:\r\nThe item is despatched and cannot be moved"}

Source Error:

Line 181: if (response.StatusCode != HttpStatusCode.OK)

Line 182: throw new ApiException(result);

Так что мой вопрос, могу ли я получить Application_Error метод получить ошибки, которые AREApiException s и вернуть ошибку как JSON?

+0

Похоже, вы забыли присвоить свой результат: 'filterContext.Result = result;' –

+0

ах да, это не проблема, но, спасибо, что указали это! – r3plica

ответ

0

So my question is, can I get the Application_Error method to get errors that ARE ApiExceptions and return the error as JSON?

Конечно:

protected void Application_Error() 
{ 
    var apiException = Server.GetLastError() as ApiException; 
    if (apiException != null) 
    { 
     Response.Clear(); 
     Server.ClearError(); 

     Response.StatusCode = 400; 
     Context.Response.ContentType = "application/json"; 
     Context.Response.Write("YOUR JSON HERE"); 
    } 
} 
+0

Это не работает, оно просто записывает содержимое в браузер и никогда не подбирается с помощью запроса ajax. – r3plica

+0

Ну, тогда вы, вероятно, должны исправить ваш запрос AJAX. Поскольку вы предоставили ровно 0 подробностей о том, как выполняется этот запрос, вполне возможно, что он сможет помочь в дальнейшем с этой проблемой. –

+0

Я сказал, что это делается из MVC, т. Е. Вызов выполняется изнутри MVC-контроллера во внешний API (похоже, я знаю, но устройство, которое я использую, действительно не поддерживает JavaScript). Во всяком случае, мне удалось решить эту проблему с исключением фильтра. Я отправлю свой ответ через минуту. – r3plica

0

В конце концов, я не нужно использовать Global.asax вообще, я был в состоянии обрабатывать все это в моем ExceptionAttribute класса, как это :

public class ExceptionAttribute : IExceptionFilter 
{ 

    /// <summary> 
    /// Handles any exception 
    /// </summary> 
    /// <param name="filterContext">The current context</param> 
    public void OnException(ExceptionContext filterContext) 
    { 

     // If our exception has been handled, exit the function 
     if (filterContext.ExceptionHandled) 
      return; 

     // Set our base status code 
     var statusCode = (int)HttpStatusCode.BadRequest; 

     // If our exception is an http exception 
     if (filterContext.Exception is HttpException) 
     { 

      // Cast our exception as an HttpException 
      var exception = (HttpException)filterContext.Exception; 

      // Get our real status code 
      statusCode = exception.GetHttpCode(); 
     } 

     // Set our context result 
     var result = CreateActionResult(filterContext, statusCode); 

     // Set our handled property to true 
     filterContext.Result = result; 
     filterContext.ExceptionHandled = true; 
    } 

    /// <summary> 
    /// Creats an action result from the status code 
    /// </summary> 
    /// <param name="filterContext">The current context</param> 
    /// <param name="statusCode">The status code of the error</param> 
    /// <returns></returns> 
    protected virtual ActionResult CreateActionResult(ExceptionContext filterContext, int statusCode) 
    { 

     // Create our context 
     var context = new ControllerContext(filterContext.RequestContext, filterContext.Controller); 
     var statusCodeName = ((HttpStatusCode)statusCode).ToString(); 

     // Create our route 
     var controller = (string)filterContext.RouteData.Values["controller"]; 
     var action = (string)filterContext.RouteData.Values["action"]; 
     var model = new HandleErrorInfo(filterContext.Exception, controller, action); 

     // Create our result 
     var view = SelectFirstView(context, string.Format("~/Views/Error/{0}.cshtml", statusCodeName), "~/Views/Error/Index.cshtml", statusCodeName); 
     var result = new ViewResult { ViewName = view, ViewData = new ViewDataDictionary<IError>(this.Factorize(model)) }; 

     // Return our result 
     return result; 
    } 

    /// <summary> 
    /// Factorizes the HandleErrorInfo 
    /// </summary> 
    /// <param name="error"></param> 
    /// <returns></returns> 
    protected virtual IError Factorize(HandleErrorInfo error) 
    { 

     // Get the error 
     var model = new Error 
     { 
      Message = "There was an unhandled exception." 
     }; 

     // If we have an error 
     if (error != null) 
     { 

      // Get our exception 
      var exception = error.Exception; 

      // If we are dealing with an ApiException 
      if (exception is ApiException || exception is HttpException) 
      { 

       // Get our JSON 
       var json = JObject.Parse(exception.Message); 
       var message = json["exceptionMessage"] != null ? json["exceptionMessage"] : json["message"]; 

       // If we have a message 
       if (message != null) 
       { 

        // Update our model message 
        model.Message = message.ToString(); 
       } 
      } 
      else 
      { 

       // Update our message 
       model.Message = exception.Message; 
      } 
     } 

     // Return our response 
     return model; 
    } 

    /// <summary> 
    /// Gets the first view name that matches the supplied names 
    /// </summary> 
    /// <param name="context">The current context</param> 
    /// <param name="viewNames">A list of view names</param> 
    /// <returns></returns> 
    protected string SelectFirstView(ControllerContext context, params string[] viewNames) 
    { 
     return viewNames.First(view => ViewExists(context, view)); 
    } 

    /// <summary> 
    /// Checks to see if a view exists 
    /// </summary> 
    /// <param name="context">The current context</param> 
    /// <param name="name">The name of the view to check</param> 
    /// <returns></returns> 
    protected bool ViewExists(ControllerContext context, string name) 
    { 
     var result = ViewEngines.Engines.FindView(context, name, null); 

     return result.View != null; 
    } 
} 

Это обрабатывается любая ошибка Mvc и для моих Api звонков, я сделал это:

/// <summary> 
    /// Used to handle the api response 
    /// </summary> 
    /// <param name="response">The HttpResponseMessage</param> 
    /// <returns>Returns a string</returns> 
    private async Task<string> HandleResponse(HttpResponseMessage response) 
    { 

     // Read our response content 
     var result = await response.Content.ReadAsStringAsync(); 

     // If there was an error, throw an HttpException 
     if (response.StatusCode != HttpStatusCode.OK) 
      throw new ApiException(result); 

     // Return our result if there are no errors 
     return result; 
    } 

Это позволило мне захватить ApiError и обработать ответ иначе, чем с любым другим исключением.