如何通过模型绑定将原始查询字符串作为控制器操作参数?

问题描述 投票:0回答:2

我想将原始查询字符串作为控制器操作参数:

/// <summary>
/// Return filtered wire transfers
/// </summary>
[HttpGet("wire-transfers")]
[ProducesResponseType(typeof(LoadResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public Task<ActionResult<ProxyLoadResult>> GetAsync(
    [BearerTokenFromHeader] string bearerToken,
    [RawQueryString] string rawQueryString,
    CancellationToken cancellationToken = default) =>
    this.TryCatchRefitCallExceptionAsync(
        () => _memberCreditorWireTransfersService
            .GetAsync(bearerToken, rawQueryString, cancellationToken));

我遵循与BearerTokenFromHeaderAttribute相同的逻辑:https://stackoverflow.com/a/59347840/4636721

RawQueryStringAttribute.cs

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
public class RawQueryStringAttribute : Attribute, IBindingSourceMetadata, IModelNameProvider
{
    public BindingSource BindingSource =>
        RawQueryStringBindingSource.Instance;

    public string? Name { get; set; }
}

RawQueryStringBindingSource.cs

public static class RawQueryStringBindingSource
{
    public const string Id = "RawQueryString";
    public const string Name = Id;

    public static readonly BindingSource Instance = new BindingSource(
        Id,
        Name,
        isGreedy: false,
        isFromRequest: true);
}

RawQueryStringValueProvider.cs

public class RawQueryStringValueProvider : BindingSourceValueProvider
{
    public RawQueryStringValueProvider(BindingSource bindingSource, string rawQueryString) : base(bindingSource) => 
        RawQueryString = rawQueryString;

    private string RawQueryString { get; }

    public override bool ContainsPrefix(string prefix) => 
        false;

    public override ValueProviderResult GetValue(string key) =>
        string.IsNullOrEmpty(key)
            ? new ValueProviderResult(RawQueryString)
            : ValueProviderResult.None;
}

RawQueryStringValueProviderFactory.cs

public class RawQueryStringValueProviderFactory : IValueProviderFactory
{
    public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
    {
        var rawQueryString = context.ActionContext.HttpContext.Request?.QueryString.Value;

        context.ValueProviders.Add(
            new RawQueryStringValueProvider(RawQueryStringBindingSource.Instance, 
                rawQueryString!));

        return Task.CompletedTask;
    }
}

但是当控制器动作通过类似这样的方式调用时:

http://localhost:5000/api/v1/wire-transfers?requireTotalCount=true&skip=0&take=5

我收到以下错误:

{
   "errors":{
      "rawQueryString":[
         "The rawQueryString field is required."
      ]
   },
   "type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
   "title":"One or more validation errors occurred.",
   "status":400,
   "traceId":"|dd22ddb4-44ebc27fb1cbc9ba."
}

不确定是否真的明白为什么,有什么想法吗?

如果要这样做也要避免任何误解:

/// <summary>
/// Return filtered wire transfers
/// </summary>
[HttpGet("wire-transfers")]
[ProducesResponseType(typeof(LoadResult), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public Task<ActionResult<ProxyLoadResult>> GetAsync(
    [BearerTokenFromHeader] string bearerToken,
    CancellationToken cancellationToken = default) =>
    this.TryCatchRefitCallExceptionAsync(
        () => _memberCreditorWireTransfersService
            .GetAsync(bearerToken, this.Request.QueryString.Value, cancellationToken));

相同的请求很好用...

我的意思是我只想将this.Request.QueryString.Value作为控制器操作参数。

c# asp.net-core model-binding
2个回答
1
投票

尝试双星号(**)catch-all参数routes

类似这样的事情应该可以帮您解决:


1
投票

好的,问题很简单:

© www.soinside.com 2019 - 2024. All rights reserved.