2013-04-16 67 views
0

我在.NET 4.5中的異步/等待功能方面遇到了困難。我在Web API控制器中使用下面的代碼來從表單中捕獲多個文件以及其他一些表單數據。我無法控制表格或數據發送方式。處理異步收到的表單數據的方法

我想要做的就是接收文件,從表單獲取數據,根據表單數據讀取數據庫,移動文件並更新另一個數據庫表。使用下面的代碼,我無法獲取文件或表單數據。我根據表單數據中傳遞的formID從數據庫中獲取數據。

這是當我取消註釋底部附近的代碼以回寫數據庫時遇到的問題。如果我有三個文件,在捕獲塊捕獲異常之前,只有其中一個文件被移動。我假設我的問題與PostFile方法是異步的事實有關。

寫這段代碼的正確方法是什麼?

public async Task<HttpResponseMessage> PostFile() 
{ 
    // Check if the request contains multipart/form-data. 
    if (!Request.Content.IsMimeMultipartContent()) 
    { 
     throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); 
    } 

    string root = GetRootPath(); 
    var provider = new MyMultipartFormDataStreamProvider(root); 
    string logfile = root + "/form_data_output.txt"; 

    try 
    { 
     // Read the form data and return an async task. 
     await Request.Content.ReadAsMultipartAsync(provider); 

     string form_id = provider.FormData.Get("FormId"); 

     string driver_id = GetDriverID(form_id); // returns an int as a string 

     string location = ConfigurationManager.AppSettings["storagePath"]; 
     location += form_id + "\\"; 

     //// make sure the new directory exists 
     if (!Directory.Exists(location)) 
     { 
      Directory.CreateDirectory(location); 
     } 

     var keys = provider.FormData.Keys.Cast<string>(); 
     foreach (var k in keys.Where(k => k.StartsWith("FormViewer") == true)) 
     { 
      string filename = provider.FormData.Get(k) + ".pdf"; 
      string type_key = "FormType_" + k.Substring(k.IndexOf('_') + 1); 
      string type_value = provider.FormData.Get(type_key); 

      // setup the full path including filename 
      string path = root + "\\" + filename; 
      string newFullPath = location + filename; 

      // move the file 
      File.Move(path, newFullPath); 
      if (File.Exists(newFullPath)) 
      { 
       if (File.Exists(newFullPath)) 
       { 
        try 
        { 
         string conn_str = ConfigurationManager.ConnectionStrings["eMaintenanceConnection"].ConnectionString; 
         using (SqlConnection conn = new SqlConnection(conn_str)) 
         { 
          SqlCommand cmd = new SqlCommand("INSERT INTO eSubmittal_Document VALUES (null,@driver_id,@location,@doctype)"); 
          cmd.Parameters.AddWithValue("@driver_id", driver_id); 
          cmd.Parameters.AddWithValue("@location", location); 
          cmd.Parameters.AddWithValue("@doc_type", type_value); 
          conn.Open(); 
          int c = await cmd.ExecuteNonQueryAsync(); 
          conn.Close(); 
         } 
        } 
        catch (Exception e) 
        { 
         LogEntry(logfile, e.Message); 
        } 
       } 
      } 
     } 

     return Request.CreateResponse(HttpStatusCode.OK); 
    } 
    catch (System.Exception e) 
    { 
     return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); 
    } 
} 
+2

什麼是你得到的異常? – GrandMasterFlush

+0

我已經更改了註釋代碼並將其封裝在try/catch塊中。異常是無效操作:連接關閉。 – fkm71

+0

我應該補充說我在GetDriverID函數的前面使用了相同的連接字符串,所以我知道連接字符串是正確的。 – fkm71

回答

1

asyncawait提供異步代碼的自然程序流程。因此,在大多數情況下,你可以考慮一下代碼,您通常想到的方式:

這是當我去掉接近底部的代碼寫回,我遇到問題的數據庫。如果我有三個文件,在捕獲塊捕獲異常之前,只有其中一個文件被移動。

下面是我從這個得到:

  • 您的數據庫代碼拋出異常。
  • 當引發異常時,它將離開foreach循環轉至catch處理程序。

無意外那裏......

+0

我同意沒有任何意外。我確實發現代碼認爲連接已關閉。我進行了更改以捕獲該異常,並在那裏創建了SqlConnection,而不是從其他函數中提取。 – fkm71

0

很難幫助很大,而不知道異常,但異步方法內執行同步數據庫操作似乎是一個壞主意給我。試着改變你的代碼中使用:

int c = await cmd.ExecuteNonQueryAsync(); 
+0

我對我的原創感到不舒服。感謝您的建議。我盯着代碼太久了。 – fkm71