在基于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框架无法正确解析查询
的图片我向第三方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
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)上的问题
答案 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