2015-09-17 25 views
1

審查,並試圖許多周圍的錯誤消息的建議後:MVC,ASP.NET身份,EmailService和異步調用W/Angularjs

「異步模塊或處理程序完成,而異步 操作仍待定「。

,我發現自己在即使調用MVC的AccountController實際執行的控制器方法所需的代碼(電子郵件被髮送到與正確的內容在正確的地方)和一個try/catch情況會不會'捕捉'錯誤,發起呼叫的AngularJS工廠將收到服務器錯誤「頁面」。

工廠:(AngularJS)

InitiateResetRequest: function (email) { 
        var deferredObject = $q.defer(); 

        $http.post(
         '/Account/InitiateResetPassword', { email: email } 
        ) 
        .success(function (data) { 
          deferredObject.resolve(data); 
        }) 
        .error(function (data) { 
         //This is a stop-gap solution that needs to be fixed..! 
         if (data.indexOf("An asynchronous module or handler completed while an asynchronous operation was still pending.") > 0) { 
          deferredObject.resolve(true); 
         } else { 
          deferredObject.resolve(false); 
         } 
        }); 
        return deferredObject.promise; 
       } 

MVC控制器(C#):

 [HttpPost] 
     [AllowAnonymous] 
     public async Task<int> InitiateResetPassword(string email) 
     { 
      try 
      { 
       _identityRepository = new IdentityRepository(UserManager); 
       string callbackUrl = Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath, "/account/reset?id="); 
       await _identityRepository.InitiatePasswordReset(email, callbackUrl); 
       return 0; 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
       return 1; 
      } 
     } 

身份存儲庫/ InitiatePasswordReset:

public async Task InitiatePasswordReset(string email, string callbackUrl) 
     { 
      try 
      { 
       var u = await _applicationUserManager.FindByEmailAsync(email); 

       string passwordResetToken = await GetResetToken(u); 
       callbackUrl = callbackUrl + HttpUtility.UrlEncode(passwordResetToken); 
       await _applicationUserManager.SendEmailAsync(u.Id, RESET_SUBJECT, string.Format(RESET_BODY, u.FirstName, u.LastName, callbackUrl)); 
      } 
      catch(Exception ex) 
      {  //another vain attempt to catch the exception... 
       Console.WriteLine(ex.ToString()); 
       throw ex; 
      } 
     } 

的EmailService注入到ASP.NET身份「ApplicationUserManager」

public class EmailService : IIdentityMessageService 
    { 
     XYZMailer xyzMailer; 
     public EmailService() 
     { 
      xyzMailer = XYZMailer.getCMRMailer(); 
     } 
     public async Task SendAsync(IdentityMessage message) 
     { 
      //original code as posted: 
      //await Task.FromResult(xyzMailer.SendMailAsync(message)); 
      //solution from @sirrocco- 
      await xyzMailer.SendMailAsync(message); 
     } 
    } 

終於......在XYZMailer類

class XYZMailer 
    { 
     #region"Constants" 
     private const string SMTP_SERVER = "XYZEXCHANGE.XYZ.local"; 
     private const string NO_REPLY = "[email protected]"; 
     private const string USER_NAME = "noreply"; 
     private const string PASSWORD = "[email protected]"; //NO, that is not really the password :) 
     private const int SMTP_PORT = 587; 
     private const SmtpDeliveryMethod SMTP_DELIVERY_METHOD = SmtpDeliveryMethod.Network; 
     #endregion//Constants 

     internal XYZMailer() 
     { 
      //default c'tor 
     } 

     private static XYZMailer _XYZMailer = null; 
     public static XYZMailer getXYZMailer() 
     { 
      if (_XYZMailer == null) 
      { 
       _XYZMailer = new XYZMailer(); 
      } 
      return _XYZMailer; 
     } 

     public async Task<int> SendMailAsync(IdentityMessage message) 
     { 
#if DEBUG 
       message.Body += "<br/><br/>DEBUG Send To: " + message.Destination; 
       message.Destination = "[email protected]"; 
#endif 
      // Create the message: 
      var mail = 
       new MailMessage(NO_REPLY, message.Destination) 
       { 
        Subject = message.Subject, 
        Body = message.Body, 
        IsBodyHtml = true 
       }; 

      // Configure the client: 
      using (SmtpClient client = new SmtpClient(SMTP_SERVER, SMTP_PORT) 
      { 
       DeliveryMethod = SMTP_DELIVERY_METHOD, 
       UseDefaultCredentials = false, 
       Credentials = new System.Net.NetworkCredential(USER_NAME, PASSWORD), 
       EnableSsl = true 
      }) 
      { 
       // Send: 
       await client.SendMailAsync(mail); 

      } 
      return 0; 
     } 

    } 

(注:原控制方法只是「公共異步任務InitiateResetPassword,我添加了返回類型爲試圖捕獲的錯誤服務器。在運行時,返回0;沒有命中(斷點)的捕獲不會被擊中和在客戶端「)

目前,我只是過濾預期的錯誤消息,並告訴JavaScript將其視爲成功。 「實際工作」 ......但它不是「理想」。

如何防止在服務器上的錯誤? 或交替, 如何捕獲錯誤的服務器上?

+1

您是否需要等待EmailService中的Task.FromResult?問題不在角度,但與C#代碼..這就是你必須看看 – sirrocco

+0

@sirrocco感謝您的問題;我已經意識到這個問題居住在C#代碼中,我提供了角度位以顯示調用來自何處以及遇到問題的位置。 IIdentityMessageService強制「SendAsync」是一個異步任務......並且我從一個等待狀態改變爲等待Task.FromResult ......這顯然不僅是「不需要的」,而是問題的根源。請將您的評論轉換爲答案,我會接受它。 –

+0

...另外:關於爲什麼這個錯誤不會被困在服務器上的想法? –

回答

1

您需要從刪除,因爲這使得代碼可以同步執行而不是異步執行。

至於爲何異常仍提出和try/catch語句外冒泡 - 我懷疑Task.FromResult是罪魁禍首這裏太 - 如果你現在在SendAsync引發異常(只是爲了測試它),你應該趕在控制器。