处理异步接收表单数据的方法

时间:2013-04-16 14:47:08

标签: c# async-await

我无法绕过.NET 4.5中的异步/等待功能。我在Web API控制器中使用下面的代码来捕获表单中的多个文件以及一些其他表单数据。我无法控制表单或如何发送数据。

我想要做的是接收文件,从表单获取数据,根据表单数据读取数据库,移动文件,以及更新另一个数据库表。使用下面的代码,我可以轻松获取文件或表单数据。我根据表单数据中传递的formID从数据库中获取数据。

当我将底部附近的代码取消注释以便写回我遇到问题的数据库时。如果我有三个文件,只有其中一个文件在catch块捕获异常之前被移动。我假设我的问题与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 个答案:

答案 0 :(得分:1)

asyncawait为异步代码提供自然程序流。因此,在大多数情况下,您可以按照通常的想法考虑代码:

  

当我将底部附近的代码取消注释以便写回我遇到问题的数据库时。如果我有三个文件,只有一个文件在catch块捕获异常之前被移动。

以下是我从中得到的结果:

  • 您的数据库代码正在抛出异常。
  • 抛出异常时,它会离开foreach循环以转到catch处理程序。

那里没什么意外......

答案 1 :(得分:0)

在不知道异常的情况下很难提供帮助,但在异步方法中执行同步数据库操作对我来说似乎不太好。尝试更改您的代码使用:

int c = await cmd.ExecuteNonQueryAsync();