"Equal"查询中的符号可选"application/x-www-form-urlencoded"?



你好,在我基于 Core 2.2 构建的项目 ASP.NET,我需要实现 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] 可能为空或空,但使用此查询时不会解析数据 [user_uid] (默认 guid)!因为 ASP.NET 框架无法正确解析查询

已分析查询的图像

我向第三方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 核心 github 上打开一个问题吗?

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

我找到了解决此问题的方法,使用中间件:

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
}

希望有帮助,雷米

最新更新