【问题标题】:How to parse form data using Azure Functions如何使用 Azure Functions 解析表单数据
【发布时间】:2017-07-28 02:57:47
【问题描述】:

我正在尝试在 Azure 函数中获取表单数据。

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info("C# HTTP trigger function processed a request.");
    NameValueCollection col = req.Content.ReadAsFormDataAsync().Result;   
    return req.CreateResponse(HttpStatusCode.OK, "OK");
}

我收到以下错误:

执行函数时出现异常:System.Net.Http.Formatting:没有 MediaTypeFormatter 可用于从媒体类型为“multipart/form-data”的内容中读取“FormDataCollection”类型的对象。

我正在尝试通过 SendGrid 解析入站电子邮件,如此处所述。 https://sendgrid.com/docs/Classroom/Basics/Inbound_Parse_Webhook/setting_up_the_inbound_parse_webhook.html

传入的请求看起来正确。

--xYzZY 内容处置:表单数据;名称="附件"

0 --xYzZY 内容处置:表单数据;名称="文本"

你好世界 --xYzZY 内容处置:表单数据;名称="主题"

主题 --xYzZY 内容处置:表单数据;名称="到"

【问题讨论】:

    标签: c# function azure sendgrid


    【解决方案1】:

    由于似乎没有将IFormCollection 转换为自定义模型/视图模型类型的好方法,因此我为此编写了一个扩展方法。

    很遗憾,Azure Functions v2/v3 尚不支持此功能。

    public static class FormCollectionExtensions
    {
        /// <summary>
        /// Attempts to bind a form collection to a model of type <typeparamref name="T" />.
        /// </summary>
        /// <typeparam name="T">The model type. Must have a public parameterless constructor.</typeparam>
        /// <param name="form">The form data to bind.</param>
        /// <returns>A new instance of type <typeparamref name="T" /> containing the form data.</returns>
        public static T BindToModel<T>(this IFormCollection form) where T : new()
        {
            var props = typeof(T).GetProperties();
            var instance = Activator.CreateInstance<T>();
            var formKeyMap = form.Keys.ToDictionary(k => k.ToUpper(), k => k);
    
            foreach (var p in props)
            {
                if (p.CanWrite && formKeyMap.ContainsKey(p.Name.ToUpper()))
                {
                    p.SetValue(instance, form[formKeyMap[p.Name.ToUpper()]].FirstOrDefault());
                }
            }
    
            return instance;
        }
    }
    

    这将尝试将IFormCollection 绑定到您传入的任何模型类型。属性名称不区分大小写(即您可以将firstname=Bob 映射到public string FirstName { get; set; }

    用法:

    var myModel = (await httpReq.ReadFormAsync()).BindToModel<MyModel>();
    

    【讨论】:

    【解决方案2】:

    根据错误消息,您正在使用 multipart/form-data 作为请求内容类型。但是您还没有将任何媒体类型数据发布到服务器。

    如果您只是想向服务器发送一些纯数据,您可以将内容类型更改为 application/x-www-form-urlencoded 并将您的请求正文修改为以下格式。

    name=attachments&anothername=anothervalue
    

    如果您想从多部分帖子中获取表单数据,您可以使用 MultipartFormDataStreamProvider。

    string filePath = "set a temp path to store the uploaded file";
    var provider = new MultipartFormDataStreamProvider(filePath);
    var multipartProvider = await req.Content.ReadAsMultipartAsync(provider);
    var formData = multipartProvider.FormData;
    

    手动解析请求正文的内容。

    string content = await req.Content.ReadAsStringAsync();
    string formdata = content.Split(';')[1];
    string[] namevalues = formdata.Split('&');
    NameValueCollection col = new NameValueCollection();
    foreach (string item in namevalues)
    {
        string[] nameValueItem = item.Split('=');
        col.Add(nameValueItem[0], nameValueItem[1]);
    }
    

    【讨论】:

    • 我更新了我的答案以提供一种从多部分请求中获取表单数据的方法。
    • 谢谢,但在这种情况下,也没有上传文件指向。
    • 由于您的请求正文格式不符合application/x-www-form-urlencoded和multipart/form-data,建议您使用string content = await req. Content.ReadAsStringAsync();并自行解析内容。我将修改我的回复以提供详细代码。
    【解决方案3】:

    要读取表单数据,你应该使用方法 ReadAsMultipartAsync:

    data = await req.Content.ReadAsMultipartAsync().ConfigureAwait(false);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-29
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      相关资源
      最近更新 更多