在ASP.NET Web API中将自定义标头参数与swashbuckle挂起调用一起使用

问题描述

我有这种怪异的行为,当我在Swagger UI(和其他API客户端)中设置自定义标头参数时,调用只是挂起并且永远不会返回,请求没有记录(我正在用DelegatHandler记录),也没有我在浏览器或API客户端(尝试过Postman)中得到响应。

我尝试了多种添加方式。最初,我将其作为方法的参数,只是更改了名称

Get(int id,[FromHeader("X-Request-ID")] Guid? x_Request_ID = null)

FromHeaderAttribute实现:

public class FromHeaderAttribute : P@R_502_6460@meterBindingAttribute
{
    public virtual string Name { get; set; }

    public override HttpP@R_502_6460@meterBinding GetBinding(HttpP@R_502_6460@meterDescriptor p@R_502_6460@meter)
    {
        return new FromHeaderBinding(p@R_502_6460@meter,p@R_502[email protected]@R_502_6460@meterName);
    }
}

public class FromHeaderBinding : HttpP@R_502_6460@meterBinding
{
    private readonly string _name;

    public FromHeaderBinding(HttpP@R_502_6460@meterDescriptor p@R_502_6460@meter,string headerName)
        : base(p@R_502_6460@meter)
    {
        if (string.IsNullOrEmpty(headerName))
        {
            throw new ArgumentNullException("headerName");
        }

        _name = headerName;
    }

    public override Task ExecuteBindingAsync(ModelMetadataProvider MetadataProvider,HttpActionContext actionContext,CancellationToken cancellationToken)
    {
        if (actionContext.Request.Headers.TryGetValues(_name,out var values))
        {
            var converter = TypeDescriptor.GetConverter(Descriptor.P@R_502_6460@meterType);
            try
            {
                actionContext.ActionArguments[Descriptor.P@R_502_6460@meterName] = converter.ConvertFromString(values.FirstOrDefault());
            }
            catch (Exception exception)
            {
                var error = new HttpError("The request is invalid.") { MessageDetail = exception.Message };
                throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,error));
            }
        }
        else if (Descriptor.IsOptional)
        {
            actionContext.ActionArguments[Descriptor.P@R_502_6460@meterName] = Descriptor.DefaultValue;
        }
        else
        {
            var error = new HttpError("The request is invalid.") { MessageDetail = $"The `{_name}` header is required." };
            throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,error));
        }

        return Task.Fromresult<object>(null);
    }
}

并且我有一个操作过滤器,用于更改客户端的字段名称

var headerP@R_502_6460@meters = apiDescription.P@R_502_6460@meterDescriptions
    .Where(p => p.P@R_502[email protected]@R_502_6460@meterBinderAttribute is FromHeaderAttribute);

if (headerP@R_502[email protected]())
{
    if (operation.p@R_502_6460@meters == null)
    {
        operation.p@R_502_6460@meters = new List<P@R_502_6460@meter>();
    }

    var temp = headerP@R_502[email protected](operation.p@R_502_6460@meters ?? new List<P@R_502_6460@meter>(),p1 => p1.Name,p2 => p2.name,(p1,p2) => new
    {
        p@R_502_6460@meterBinding = p1.P@R_502[email protected]@R_502_6460@meterBinderAttribute as FromHeaderAttribute,p@R_502_6460@mterDescription = p1,operationP@R_502_6460@meter = p2
    })
    .ToList();

    temp.ForEach(p =>
    {
        p.operationP@R_502[email protected](p.operationP@R_502_6460@meter);

        operation.p@R_502[email protected](new P@R_502_6460@meter
        {
            name = p.p@R_502[email protected],@in = "header",description = p.operationP@R_502[email protected],type = p.operationP@R_502[email protected],required = p.operationP@R_502_6460@meter.required,format = p.operationP@R_502[email protected]
        });
    });
}

后来我将最后一部分更改为简单:

p.operationP@R_502[email protected] = p.p@R_502[email protected];
p.operationP@R_502_6460@meter.@in = "header";

代替添加/删除参数。

问题是,无论何时传递了无效的GUID(uuid v4),调用都被挂起,从未返回,并且在我的代码中未记录任何内容,但是IIS日志显示该请求以预期的结果传递了。调试时,我的代码也没有在ExecuteBindingAsync中中断。

如果Guid格式正确,则一切正常。

我发现改名是(最有可能的)主要问题,当测试除改名外的所有内容都相同时,即只是过滤器而已:

p.operationP@R_502_6460@meter.@in = "header";

每次都能很好地工作,但是Swagger中的标头是x_Request_ID。我以为名称更改是问题所在,因此为了进行测试,创建了一个简单的方法,在其中我刚刚添加一个新参数:

if (operation.operationId == "API_Get2")
{
    operation.p@R_502[email protected](new P@R_502_6460@meter
    {
        name = "X-Request-ID",description = "Request ID",type = "string",required = false
        format = "uuid"
    });
}

,并将操作的签名更改为:

Get(int id)

但是,无论它是有效还是无效的GUID,它每次都挂起。

我一直在试图找出原因,以及如何正确地以大张旗鼓显示自定义标头,并使代码正常解析两天,而且没有运气。我还尝试了ModelBinding,但是在那种情况下,标题只是被忽略了。

对我来说,如果标头是操作的参数,还是不一样,我只是希望它能以准确的说明显示出来。

非常感谢您对我在这里错过的任何解决方案或问题的指点。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)