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

C# 处理异步接收的表单数据的方法,c#,async-await,C#,Async Await,我很难理解.NET4.5中的异步/等待功能。我在Web API控制器中使用下面的代码来捕获表单中的多个文件以及一些其他表单数据。我无法控制表单或表单如何发送数据 我要做的是接收文件,从表单获取数据,根据表单数据读取数据库,移动文件,并更新另一个数据库表。使用下面的代码,我可以轻松获取文件或表单数据。我根据表单数据中传递的formID从数据库中获取数据 当我取消注释靠近底部的代码以便写回数据库时,我遇到了问题。如果我有三个文件,在catch块捕获异常之前,只有一个文件被移动。我假设我的问题与Pos

我很难理解.NET4.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);
    }
}
public异步任务PostFile()
{
//检查请求是否包含多部分/表单数据。
如果(!Request.Content.IsMimeMultipartContent())
{
抛出新的HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
字符串root=GetRootPath();
var provider=新的MyMultipartFormDataStreamProvider(根);
字符串logfile=root+“/form_data_output.txt”;
尝试
{
//读取表单数据并返回异步任务。
wait Request.Content.ReadAsMultipartAsync(提供程序);
字符串form_id=provider.FormData.Get(“FormId”);
string driver_id=GetDriverID(form_id);//以字符串形式返回int
字符串位置=ConfigurationManager.AppSettings[“storagePath”];
位置+=表格id+“\\”;
////确保新目录存在
如果(!Directory.Exists(location))
{
CreateDirectory(位置);
}
var keys=provider.FormData.keys.Cast();
foreach(键中的变量k,其中(k=>k.StartsWith(“FormViewer”)==true))
{
字符串文件名=provider.FormData.Get(k)+“.pdf”;
string type=“FormType”+k.Substring(k.IndexOf(“”“)+1);
字符串类型\u值=provider.FormData.Get(类型\u键);
//设置包含文件名的完整路径
字符串路径=根+“\\”+文件名;
字符串newFullPath=位置+文件名;
//移动文件
File.Move(路径,newFullPath);
if(File.Exists(newFullPath))
{
if(File.Exists(newFullPath))
{
尝试
{
string conn_str=ConfigurationManager.ConnectionStrings[“eMaintenanceConnection”]。ConnectionString;
使用(SqlConnection conn=newsqlconnection(conn_str))
{
SqlCommand cmd=newsqlcommand(“插入到eSubmittal_文档值中(null,@driver_id,@location,@doctype)”;
cmd.Parameters.AddWithValue(“@driver\u id”,driver\u id);
cmd.Parameters.AddWithValue(“@location”,location);
cmd.Parameters.AddWithValue(“@doc\u type”,type\u value);
conn.Open();
int c=await cmd.ExecuteNonQueryAsync();
康涅狄格州关闭();
}
}
捕获(例外e)
{
日志条目(日志文件、电子消息);
}
}
}
}
返回Request.CreateResponse(HttpStatusCode.OK);
}
捕获(System.e例外)
{
返回请求.CreateErrorResponse(HttpStatusCode.InternalServerError,e);
}
}

如果不知道异常情况,很难提供很多帮助,但是在异步方法中执行同步数据库操作对我来说似乎是个坏主意。尝试更改代码以使用:

int c = await cmd.ExecuteNonQueryAsync();

async
wait
为异步代码提供自然的程序流。因此,在大多数情况下,您可以按照通常的方式思考代码:

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

以下是我从中得到的:

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

没有什么意外的…

您会遇到什么异常?我已经更改了注释代码,并将其包装在一个try/catch块中。异常是无效操作:连接已关闭。我应该补充一点,我在GetDriverID函数前面使用了相同的连接字符串,这样我就知道连接字符串是正确的。哇。我想我现在很尴尬。我使用的SqlCommand代码没有包含连接变量。一旦我改变了,我很好。我对我原来的感觉很不舒服。谢谢你的建议。我盯着代码看得太久了。我同意没有什么意外。我确实发现代码认为连接已关闭。我进行了更改以捕获该异常,并在那里创建了SqlConnection,而不是从另一个函数中提取。