如何使用 Azure Functions 解析表单数据

use*_*155 6 c# function azure sendgrid

我正在尝试在 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");
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

执行函数时出现异常: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 内容配置:表单数据;名称=“文本”

Hello world --xYzZY 内容配置:表单数据;名称=“主题”

主题 --xYzZY 内容配置:表单数据;名称=“到”

qJa*_*ake 5

由于似乎没有一种好的方法可以将 an 转换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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

用法:

var myModel = (await httpReq.ReadFormAsync()).BindToModel<MyModel>();
Run Code Online (Sandbox Code Playgroud)


Amo*_*mor 2

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

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

name=attachments&anothername=anothervalue
Run Code Online (Sandbox Code Playgroud)

如果您想从多部分帖子中获取表单数据,您可以使用 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;
Run Code Online (Sandbox Code Playgroud)

手动解析请求体的内容。

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]);
}
Run Code Online (Sandbox Code Playgroud)