• ASP.NET MVC请求参数字符串之区分空与NULL


    开发中经常会写增删改查的功能,这里记录下在更新操作时遇到的一个问题。

    假设一个模型对应数据库中某一张表,在更新时便需要区分是一次性更新全部字段还是仅更新部分字段。希望能做到传递某个参数时便更新,未传递时不更新。

    先定义一个用户模型,如下:

    public class UserModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
    }
    

    服务端以这种方式来接收:

    public IActionResult Update(UserModel user)
    {
        // 执行数据库更新操作
        return Content(user.Id + user.Name + user.Address);
    }
    

    然后客户端以下面的方式来请求(这里用GET方式):

    /user/update?id=1&address=hang&name=Hale
    /user/update?id=1&address=hang&name=
    /user/update?id=1&address=hang
    

    上面有三种传参方式,一般情况下没有问题,但对于第二种形式,&name= 的方式,原本是希望将name字段更新为空值,但是在Action里接收时会发现,user.Name == null 。这样便无法区分是要将Name更新为空值,还是不做更新。

    ModelBinder的方式

    默认MVC在构造参数模型时没有区分这两种情况,要实现我们的需求就需要自定义一个ModelBinder。定义一个类,并实现IModelBinder接口即可。

    public class StringBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            throw new NotImplementedException();
        }
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.FieldName);
    
            if (valueProviderResult == ValueProviderResult.None)
                return Task.CompletedTask;
    
            bindingContext.Result = ModelBindingResult.Success(valueProviderResult.FirstValue);
            return Task.CompletedTask;
        }
    }
    

    它提供两个方法来绑定模型,一个同步的一个异步的。我用的 asp.net core 是调用的异步版方法,所以这里仅实现了BindModelAsync。

    以这种方式来用这个StringBinder:

    public class UserModel
    {
        public int Id { get; set; }
        [ModelBinder(typeof(StringBinder))]
        public string Name { get; set; }
        [ModelBinder(typeof(StringBinder))]
        public string Address { get; set; }
    }
    

    这样,再以上面第二种方式传参时,便会发现user.Name == "",而不是 user.Name == null。
    这个StringBinder还可以直接用在Action的参数上:

    public IActionResult Update(UserModel user, [ModelBinder(typeof(StringBinder))]string v, string v2)
    {
        return Content(user.Id + user.Name + v + v2);
    }
    

    这里参数 v 和 v2,一个指定了Binder一个未指定,以下面方式调用以下即可看出区别:

    /user/update?id=1&address=&name=Ingo&v=&v2=
    

    会发现 user.Address == "" ,v == "", v2 == null。

    简单的方式

    除了自定义ModelBinder的方式,还可以通过直接修改属性的set访问器的办法来区分null和空字符串。
    修改下UserModel的代码,新增一个Phone成员:

    private string phone;
    public string Phone
    {
        get => phone;
        set => phone = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
    

    采用与上面相同的方式传值,会发现当传递&phone=时,user.Phone == "", 同样也能区分phone是传递的空字符串还是没传递phone参数。
    因为mvc在收到&phone=参数时会调用set访问器,只是value为null。而未收到&phone=xx参数时,不会调用set访问器,所以用这种办法也可以区分空值和null。

  • 相关阅读:
    阿里云服务器CentOS系统putty登录安全组设置
    5!(简单的了解for循环与递归的区别)
    一个简单的九九乘法表的打印输出,对for循环的认识
    6.SpringCloud学习(六)——Spring Cloud Bus 消息总线
    5.SpringCloud学习(五)——Spring Cloud Config 配置中心
    3.SpringCloud学习(三)——Spring Cloud Hystrix 服务降级
    2.SpringCloud学习(二)——Spring Cloud Eureka 服务注册中心
    1.SpringCloud学习(一)——Spring Cloud Ribbon 实现负载均衡
    17.SpringBoot学习(十七)——Spring Boot 自定义Starter
    16.SpringBoot学习(十六)——Spring Boot MessageConverter消息转换器
  • 原文地址:https://www.cnblogs.com/coloc/p/8309299.html
Copyright © 2020-2023  润新知