2015-07-21 2 views
1

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

Мой метод асинхронного контроллера называется несколько раз, где я отправляю только один запрос ajax. Ответ должен быть отправлен, но, глядя на вкладку сети в панели отладки Firefox, я не вижу ответа; функция обработчика ошибок ajax также имеет readyState = 0. Это происходит только тогда, когда исключение выбрасывается внутри метода асинхронного контроллера.

Есть три/четыре части этой проблемы:

  • Мой Javascript
  • Мой метод управления асинхронной
  • Асинхронный частный метод контроллера вызывается второй
  • Методы JsonError и JsonSuccess форматирования ответ

Ajax call:

function test() { 

    var data = { 
     campagneId: 15, 
     tiersNum: 2721 
    }; 

    console.debug("Starting Ajax !"); 

    $.ajax({ 
     url: "/CampagnesMailing/SendMail", 
     data: data, 
     method: "POST", 
     success: function (response) { 
      console.debug("Sent mail successfully!"); 
     }, 
     error: function (xhr, ajaxOpt, thrownError) { 
      console.error("Error!"); 
      console.error(xhr); //xhr.readyState is 0 
      console.error(ajaxOpt); 
      console.error(thrownError); //this is empty 
     }, 
     complete: function() { 
      console.debug("Finished ajax call!"); 
     } 
    }); 
} 
$("#goButton").on("click", test); 

Асинхронный метод контроллера вызывается AJAX:

[HttpPost] 
public async Task<ActionResult> SendMail(int campagneId, int tiersNum) 
{ 
    try 
    { 
     MailMessage mail = await GetMailFor(campagneId, tiersNum); //I tried adding .ConfigureAwait(false) with no change 
     return JsonSuccess(); 
    } 
    catch (Exception e) 
    { 
     return JsonError(e); 
    } 
} 

Асинхронный метод GetMailFor:

private async Task<MailMessage> GetMailFor(int campagneId, int tiersNum) 
{ 
    try 
    { 
     MailMessage mail = new MailMessage(); 

     mail.To.Add(new MailAddress("")); // This throws an ArgumentException 

     return mail; 
    } 
    catch (Exception e) 
    { 
     throw; 
    } 
} 

JsonError/JsonSuccess:

protected JsonResult JsonSuccess() 
{ 
    Response.StatusCode = (int) System.Net.HttpStatusCode.OK; 
    Response.StatusDescription = "SUCCESS"; 
    return Json(new { success = true }, JsonRequestBehavior.AllowGet); 
} 
protected JsonResult JsonError(Exception e) 
{ 
    Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError; 
    Response.StatusDescription = e.Message; 
    //HttpContext.ApplicationInstance.CompleteRequest(); 
    return Json(new {e.Message}, JsonRequestBehavior.AllowGet); 
} 

Когда я поставил точку останова на первой строка SendMail (одна с MailMessage mail = await GetMailFor(campagneId, tiersNum);) a nd точка останова в catch, я вижу, что метод вызывается 7 раз и каждый раз попадает в catch, в основном с разными значениями ManagedThreadId в System.Threading.Thread.CurrentThread.

Как ни странно, если я заменю вызов mail.To.Add() на throw new ArgumentException("Boom");, процесс идет хорошо, и только один вызов поймал в моих контрольных точках.

Я посмотрел this issue, но добавив HttpContext.ApplicationInstance.CompleteRequest(); до return Json(new {e.Message}, JsonRequestBehavior.AllowGet); ничего не изменил.

Я вижу только 1 запрос POST на вкладке «Сеть» от firefox. Это никогда не получает никакого ответа. Обратите внимание, что этих фрагментов достаточно, чтобы вызвать проблему, но я использую больше кода в реальном приложении (нет необходимости предупреждать меня об асинхронном методе, не ожидающем).

Что происходит? Почему SendMail называется 7 раз? Почему только, когда new MailAddress() бросает, а не когда я бросаю вручную? Как я могу отлаживать такое поведение?

EDIT: Удаление попытки/улова изнутри метода GetMailFor не дает никаких изменений.
EDIT2: Удаление любого упоминания о async, Task<T> или await также не дает никаких изменений, так что это не имеет ничего общего с async проблемы. Я сейчас потерялся, потому что не знаю, как отлаживать это ...
EDIT3: Я никогда не войти в функцию Application_Error, но я вхожу Application_BeginRequest каждый раз перед входом SendMail и Application_EndRequest каждый раз после возвращения JsonError

+0

Является ли это контроллер MVC или WebAPI? –

+0

MVC, извините, я забыл пометить его. – Eregrith

+0

Я не понимаю, почему все это «асинк»? – DavidG

ответ

2

Попытки сумасшедшие вещи случайно, я наткнулся на реальной проблеме: JsonError добавлял сообщение об исключении как Response.StatusDescription, в то время как сообщение содержало \r\n. Это как-то нарушило обработку запросов.

Исправление просто изменить JsonError к:

protected JsonResult JsonError(Exception e) 
{ 
    Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError; 
    Response.StatusDescription = e.Message.Replace("\r\n", " | "); 
    return Json(new {e.Message}, JsonRequestBehavior.AllowGet); 
} 
+0

Я понял, если проблема не возникает, когда я бросаю ее вручную, она должна находиться в различиях между «ArgumentException» и «броском», созданным «new MailAddress (« »).'. Видел '\ r \ n' и думал:« Хм ... это было бы ужасно, если бы это что-то ... » – Eregrith

+0

Имеет смысл ... теперь нам просто нужно подождать, пока Джон Скит объяснит, почему' '\ r \ n "" нарушает обработку запроса ^^ –

+0

[Почему запрос нарушен] (http://stackoverflow.com/a/11917247/1151654) – Eregrith

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