“平等”符号在“ application / x-www-form-urlencoded”查询中是可选的?

时间:2019-07-19 20:53:15

标签: c# asp.net asp.net-core rfc

在基于ASP.NET Core 2.2的项目中,您好,我需要实现webhook来处理来自第三方API的“通知”。

我们先部署它,然后进行测试,但是每个请求都属于400个错误请求。 我进行调查,然后检测到发送的请求的主体(application / x-www-form-urlencoded)在查询&data [subject_name]&data [user_uid] 中,例如包含“缺少”等号:

webhook_type=create&network_name=test&data[id]=389&data[action_name]=action&data[target_name]=target&data[subject_name]&data[user_uid]=b6643dc6-946b-490a-86b8-eb5c67f82bca&data[type]=Comment

data [subject_name]可以为null或为空,但使用此查询无法解析data [user_uid](默认guid)!因为ASP.NET框架无法正确解析查询

parsed query

的图片

我向第三方API开发人员提出了两种解决方案: 1.在字段为空或为空时强制添加“等于”符号

webhook_type=create&network_name=test&data[id]=389&data[action_name]=action&data[target_name]=target&data[subject_name]=&data[user_uid]=b6643dc6-946b-490a-86b8-eb5c67f82bca&data[type]=Comment
  1. 从查询中删除空字段或空字段
webhook_type=create&network_name=test&data[id]=389&data[action_name]=action&data[target_name]=target&data[user_uid]=b6643dc6-946b-490a-86b8-eb5c67f82bca&data[type]=Comment

答案是:“ 不,这是我们不做任何更改的标准

这里是模型

public class WebHookDto<T> where T : ThirdPartyNotificationDto
{
    [Required]
    [EnumDataType(typeof(WebHookType))]
    [FromForm(Name = "webhook_type")]
    public WebHookType WebHookType { get; set; }

    [Required]
    [MinLength(1)]
    [FromForm(Name = "network_name")]
    public string NetworkName { get; set; }

    [Required]
    [FromForm(Name = "data")]
    public T Data { get; set; }
}

public class ThirdPartyNotificationDto
{
    [Required]
    [FromForm(Name = "id")]
    public long Id { get; set; }
}

public class UserNotificationDto : ThirdPartyNotificationDto
{
    [Required]
    [FromForm(Name = "user_uid")]
    public Guid UserId { get; set; }

    [FromForm(Name = "action_name")]
    public string ActionName { get; set; }

    [FromForm(Name = "target_name")]
    public string TargetName { get; set; }

    [FromForm(Name = "subject_name")]
    public string SubjectName { get; set; }

    [Required]
    [EnumDataType(typeof(NotificationTargetType))]
    [FromForm(Name = "type")]
    public NotificationTargetType TargetType { get; set; }
}

此处是控制器/操作

[HttpPost("user")]
public AcceptedResult UserNotificationListener([FromForm]WebHookDto<UserNotificationDto> request)
{
    // some code that validate the query or throw exception
}

完整的查询

POST /api/v1/notification/user HTTP/1.1
Host: localhost:44300
Content-Type: application/x-www-form-urlencoded

webhook_type=create&network_name=test&data[id]=389&data[action_name]=action&data[target_name]=target&data[subject_name]&data[user_uid]=b6643dc6-946b-490a-86b8-eb5c67f82bca&data[type]=Comment

我的问题是:

可选的“等于”符号是否像第三方开发人员所说的那样是标准?

如果第三方开发人员坚持其立场,什么是解决此问题的最佳方法?

您认为我需要为此在ASP.NET Core github上发布一个问题吗?

编辑#1:[asp.net核心github](https://github.com/aspnet/AspNetCore/issues/12381)上的问题

1 个答案:

答案 0 :(得分:1)

我发现了使用中间件解决此问题的方法:

app.UseMiddleware<RemoveInvalidFormKeysMiddleware>();
app.UseMvc();

此中间件将重写Request.Forms中的“无效”键

public class RemoveInvalidFormKeysMiddleware
{
    private readonly RequestDelegate next;

    public RemoveInvalidFormKeysMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        Dictionary<string, StringValues> validForm = new Dictionary<string, StringValues>();

        foreach (var form in context.Request.Form)
        {
            if (!form.Key.Contains('&'))
            {
                validForm.Add(form.Key, form.Value);
                continue;
            }

            string key = form.Key.Substring(form.Key.LastIndexOf('&') + 1);

            if (!string.IsNullOrWhiteSpace(key))
            {
                validForm.Add(key, form.Value);
            }
        }

        context.Request.Form = new FormCollection(validForm);

        await next(context);
    }
}

然后我们可以保留其余逻辑,而无需进行其他任何更改

[HttpPost("user")]
public AcceptedResult UserNotificationListener([FromForm]WebHookDto<UserNotificationDto> request)
{
    // some code that validate the query or throw exception
}

希望它会有所帮助,Rémi