如何让 ASP.NET Core 支持绑定查询字符串中的数组(2)

前言

上回说到,我们实现了IntArrayModelBinder,可以让 ASP.NET Core 绑定查询字符串中的数组。但是必须显示指定ModelBinder

public string Get([FromQuery][ModelBinder(BinderType = typeof(IntArrayModelBinder))] int[] values)

而官方提供的ByteArrayModelBinder不需要指定ModelBinder即可生效:

public string Get([FromQuery]byte[] values)

那么,它是如何做到的呢?

ByteArrayModelBinderProvider

在源码中查找ByteArrayModelBinder的所有引用。发现只有一处使用:

public class ByteArrayModelBinderProvider : IModelBinderProvider
{
    /// <inheritdoc />
    public IModelBinder? GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
 
        if (context.Metadata.ModelType == typeof(byte[]))
        {
            var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
            return new ByteArrayModelBinder(loggerFactory);
        }
 
        return null;
    }
}

MvcCoreMvcOptionsSetup

继续查找ByteArrayModelBinderProvider的所有引用。发现也只有一处使用:

internal class MvcCoreMvcOptionsSetup : IConfigureOptions<MvcOptions>, IPostConfigureOptions<MvcOptions>
{
    public void Configure(MvcOptions options)
    {
        ...

        options.ModelBinderProviders.Add(new ByteArrayModelBinderProvider());

        ...
    }
}

那么,现在的思路就是,实现IntArrayModelBinderProvider,然后调用options.ModelBinderProviders.Add(new IntArrayModelBinderProvider());

现在,关键就在于这个MvcOptions在哪访问?

AddControllers 方法

继续查找MvcOptions的所有引用。发现使用的地方不少,但是,其中有一个扩展方法:

public static IMvcBuilder AddControllers(this IServiceCollection services, Action<MvcOptions>? configure)

IServiceCollection是可以在 Startup.cs 中访问的:

public void ConfigureServices(IServiceCollection services)

实现

接下来就好办了。

  1. 实现IntArrayModelBinderProvider

public class IntArrayModelBinderProvider : IModelBinderProvider
{ 
    public IModelBinder? GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType == typeof(int[]))
        {
            return new IntArrayModelBinder();
        }

        return null;
    }
}
  1. 修改 Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.ModelBinderProviders.Insert(0, new IntArrayModelBinderProvider());
    });
}
  1. 测试一下,执行成功:

[HttpGet]
public string Get([FromQuery]int[] values)
{
    return string.Join(" ", values.Select(p => p.ToString()));
}

df1eab7a9f414bb2eba1399a1ce8d751.png

结论

通过IntArrayModelBinderProvider,我们无需显示指定ModelBinder。即可让 ASP.NET Core 自动使用IntArrayModelBinder

添加微信号【MyIO666】,邀你加入技术交流群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值