【问题标题】:Custom model binder for QueryString string parameters in ASP.NET Core 3.1?ASP.NET Core 3.1 中 QueryString 字符串参数的自定义模型绑定器?
【发布时间】:2020-09-28 07:34:50
【问题描述】:

我想为某些数据类型实现一些/任何自定义行为,例如 DateTimeint

我创建了一个自定义 JsonConverter,其中包含从请求正文接收到的数据(除非它被指定为非 json),这让我可以做到这一点。

但如果数据是在请求的查询字符串中传递的,例如?param1=helloWorld&param2=123",它们的处理方式会有所不同,并且不会被我的自定义JsonConverter 覆盖。

我已经阅读了有关创建/实现我自己的自定义模型绑定器的信息,但从外观上看是针对复杂类型的,所以我对如何准确地修改传入的查询字符串参数或者是否这是不可能的——获得对整个查询字符串的访问权限,搜索我要修改的参数,然后修改这些参数。 (与Action 方法解耦,类似于过滤器之类的。)

谢谢!

【问题讨论】:

    标签: c# parsing asp.net-core model-view-controller model-binding


    【解决方案1】:

    创建/实现我自己的自定义模型绑定器,但是从外观上看是针对复杂类型的,所以我对如何修改传入的查询字符串参数有点迷茫

    您可以创建自定义模型绑定器并将其应用于简单类型参数,如下所示。

    public IActionResult Test(string param1, [ModelBinder(BinderType = typeof(Param2ModelBinder))]int param2)
    {
    

    与 Action 方法解耦,类似于过滤器之类的。

    如果您不想直接将自定义模型绑定器应用于操作参数,您可以实现自定义模型绑定器提供程序并指定您的绑定器操作的参数,然后将其添加到 MVC 的提供程序集合中。

    Param2ModelBinder 类

    public class Param2ModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }
    
            // ...
            // implement it based on your actual requirement
            // code logic here
            // ...
    
            var model = 0;
    
            if (bindingContext.ValueProvider.GetValue("param2").FirstOrDefault() != null)
            {
                model = JsonSerializer.Deserialize<int>(bindingContext.ValueProvider.GetValue("param2").FirstOrDefault());
    
                // just for testing purpose
                // if received data > 100
                // set it to 100
    
                if ((int)model > 100)
                {
                    model = 100;
                }
            }
    
    
            bindingContext.Result = ModelBindingResult.Success(model);
            return Task.CompletedTask;
        }
    }
    

    MyCustomBinderProvider 类

    public class MyCustomBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            // specify the parameter your binder operates on
            if (context.Metadata.ParameterName == "param2")
            {
                return new BinderTypeModelBinder(typeof(Param2ModelBinder));
            }
    
            return null;
        }
    }
    

    添加自定义模型绑定器提供程序

    services.AddControllersWithViews(opt=> {
        opt.ModelBinderProviders.Insert(0, new MyCustomBinderProvider());
    });
    

    测试结果

    【讨论】:

    • 是否可以根据类型而不是参数名称来调用自定义模型绑定器?这种方式参数命名不限于“param2”并且可以是任何东西,因为自定义绑定器会查找类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    相关资源
    最近更新 更多