2011-01-16 2 views
106

Как обрабатывать исключения, созданные в контроллере, когда jquery ajax вызывает действие?ASP.NET MVC Ajax Обработка ошибок

Например, мне нужен глобальный код javascript, который будет выполняться при любом исключении сервера во время вызова ajax, который отображает сообщение об исключении, если оно находится в режиме отладки или просто обычное сообщение об ошибке.

На стороне клиента я вызову функцию по ошибке ajax.

На стороне сервера, нужно ли написать пользовательский фильтр действий?

+8

См. [Beckelmans post] (http://beckelman.net/post/2010/03/18/Handling-Errors-During-Ajax-Calls-With-ASPNET-MVC.aspx) для хорошего примера. Даринс отвечает на это сообщение, но не устанавливает правильный код состояния для ошибки. – Dan

+6

К сожалению, эта ссылка сейчас не работает –

+1

Вот ссылка на машину обратного пути: https://web.archive.org/web/20111011105139/http://beckelman.net/post/2010/03/18/Handling-Errors- Во время-Ajax-Calls-With-ASPNET-MVC.aspx – BruceHill

ответ

151

Если сервер отправляет код состояния, отличный от 200, обратный вызов ошибки выполняется:

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

и зарегистрировать глобальный обработчик ошибок можно использовать $.ajaxSetup() метод:

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

Другой путь - использовать JSON. Таким образом, вы могли бы написать фильтр пользовательских действий на сервере, который перехватывает исключение и преобразует их в 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 
     }; 
    } 
} 

, а затем украсить ваше действие контроллера с этим атрибутом:

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

и, наконец, вызвать его:

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

Спасибо за это, последнее было тем, что я искал. Итак, для исключения asp.net mvc существует ли какой-то конкретный способ, чтобы я мог его бросить, чтобы его можно было поймать обработчиком ошибок jquery? –

+1

@Lol coder, как бы вы ни выбрали исключение внутри действия контроллера, сервер вернет 500 код состояния и будет выполнен обратный вызов 'error'. –

+0

Спасибо, отлично, только то, что я искал. –

0

для обработки ошибок с Ajax вызовов на стороне клиента, вы назначаете функцию к error опции вызова Ajax.

Чтобы установить глобальный стандарт по умолчанию, вы можете использовать функцию, описанную здесь: http://api.jquery.com/jQuery.ajaxSetup.

+0

Ответ, который я дал более 4 лет назад, внезапно получает голосующий голос? Кто-нибудь хочет объяснить причину? –

+1

Обратитесь в SOF и попросите своего DBA запросить, кто подал голос. Затем сообщите об этом человеку, чтобы они могли объяснить. Не каждый может объяснить причину. – JoshYates1980

69

После прибегая к помощи я пишу простой Exception вручая на основе 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); 
     } 
    } 
} 

и писать в global.ascx:

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

, а затем написать этот скрипт на странице макета или Master :

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

Наконец, вы должны включить пользовательскую ошибку. , а затем наслаждайтесь :)

+0

Я вижу ошибку в Firebug, но не перенаправляется на страницу с ошибкой.? – user2067567

+1

Спасибо за это! должен быть помечен как ответ IMO как его фильтрация на запросы ajax и наследует правильный класс, а не тот, который наследует HandleErrorAttribute. –

+2

Замечательный ответ! : D –

2

Я сделал быстрое решение, потому что у меня не хватило времени, и все получилось нормально. Хотя я думаю, что лучшим вариантом является использование фильтра исключений, возможно, мое решение может помочь в том случае, если требуется простое решение.

Я сделал следующее.В методе контроллера я вернулся JsonResult с имущества «Успех» внутри данных:

[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 }, }; 
    } 

Позже в Ajax вызова я просто попросил для этого свойства, чтобы знать, если у меня было исключение:

$.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.') 
    } 
}); 

Надеюсь, это поможет. Счастливый код! : P

9

К сожалению, ни один из ответов не подходит для меня. Удивительно, что решение намного проще. Возврат от контроллера:

return new HttpStatusCodeResult(HttpStatusCode.BadRequest, e.Response.ReasonPhrase); 

И обрабатывайте его как стандартную HTTP-ошибку на клиенте по своему усмотрению.

+0

Что означает «e» в вашем фрагменте кода? –

+0

@Will Хуан: имя экземпляра исключения – schmendrick

+0

Мне нужно передать первый аргумент 'int'. Кроме того, когда я это делаю, результат передается обработчику 'ajax' success', а не обработчику' error'. Это ожидаемое поведение? –

4

По соглашению с ответом алехо вот полный пример. Он работает как шарм и очень прост.

Код контроллера

[HttpGet] 
public async Task<ActionResult> ChildItems() 
{ 
    var client = TranslationDataHttpClient.GetClient(); 
    HttpResponseMessage response = await client.GetAsync("childItems); 

    if (response.IsSuccessStatusCode) 
     { 
      string content = response.Content.ReadAsStringAsync().Result; 
      List<WorkflowItem> parameters = JsonConvert.DeserializeObject<List<WorkflowItem>>(content); 
      return Json(content, JsonRequestBehavior.AllowGet); 
     } 
     else 
     { 
      return new HttpStatusCodeResult(response.StatusCode, response.ReasonPhrase); 
     } 
    } 
} 

Javascript код в представлении

var url = '@Html.Raw(@Url.Action("ChildItems", "WorkflowItemModal")'; 

$.ajax({ 
    type: "GET", 
    dataType: "json", 
    url: url, 
    contentType: "application/json; charset=utf-8", 
    success: function (data) { 
     // Do something with the returned data 
    }, 
    error: function (xhr, status, error) { 
     // Handle the error. 
    } 
}); 

Надеется, что это помогает кто-то другое!

Смежные вопросы