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

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

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

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。

ASP.NET MVC请求参数字符串之区分空与NULL的更多相关文章

  1. 自动化CodeReview - ASP.NET Core请求参数验证

    自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 参数验证实现 在做服务端开发 ...

  2. 如何将ASP.NET MVC所有参数均自动设置为默认

    今天看到CSDN上有个问题觉得有点意思:"可不可以ASP.NET MVC所有参数均自动设置为默认" public class HomeController : Controller ...

  3. Spring3 MVC请求参数获取的几种方法

    Spring3 MVC请求参数获取的几种方法 一.      通过@PathVariabl获取路径中的参数 @RequestMapping(value="user/{id}/{name}&q ...

  4. ASP.NET MVC传送参数至服务端

    ASP.NET MVC传送参数至服务端,前端与服务端的写法,你可以参考与采用适合你的需求的.当你只传递一两个参数也许觉得没有什么,如果一个方法中带的参数多的话,可以考虑model,前端可以考虑对象进行 ...

  5. Spring3 MVC请求参数获取的几种方法[转]

    Spring3 MVC请求参数获取的几种方法 Spring3 MVC请求参数获取的几种方法 一.      通过@PathVariabl获取路径中的参数 @RequestMapping(value=& ...

  6. Asp.net Mvc 请求是如何到达 MvcHandler的——UrlRoutingModule、MvcRouteHandler分析,并造个轮子

    这个是转载自:http://www.cnblogs.com/keyindex/archive/2012/08/11/2634005.html(那个比较容易忘记,希望博主不要生气的) 前言 本文假定读者 ...

  7. 【MVC】ASP.NET MVC 请求生命周期

    当一个asp.net mvc应用程序提出请求,为了响应请求,包含一些请求执行流程步骤! 在asp.net mvc应用程序Http request和Http response 过程中,主要包含8个步骤: ...

  8. Spring MVC请求参数绑定 自定义类型转化 和获取原声带额servlet request response信息

    首先还在我们的框架的基础上建立文件 在domian下建立Account实体类 import org.springframework.stereotype.Controller; import org. ...

  9. ASP.NET MVC显示HTML字符串

    一些html经HtmlEncode后,如“<span>测试数据</span>”.现需要把这些内容正常显示于asp.net mvc的视图内. 举个例子来解决与说明,先创建一个mo ...

随机推荐

  1. 洛谷 P2897 【蚯蚓】 题解

    先分析一下题意: 这个题说的就是一开始给你很多条蚯蚓,然后给出你规定的次数,每一次都从蚯蚓里面拿出最长的来切成一条是原来q倍的,另一条是原来的(1 - q)倍,把切开的两条再放回去.规定次数完成之后, ...

  2. ICEM-结构化网格interface的做法

    原视频下载地址:http://yunpan.cn/cLHTCfRVNmihZ  访问密码 2ead

  3. go 练习:HTTP 处理

    这篇文章只是联系go指南时的笔记吧. package main import ( "fmt" "log" "net/http" ) type ...

  4. rust猜数游戏代码

    use std::io; use rand::Rng; use std::cmp::Ordering; fn main() { println!("Guess the number!&quo ...

  5. [C++] const和mutable关键字使用方法

    const 修饰的变量为常成员变量,表示此变量不能被修改赋值,并且构造函数中只能用初始化列表的方式初始化,其他初始化方式都是错误的 const 修饰的函数为常成员函数,表示此函数中只能读取成员变量,不 ...

  6. Fabric.js canvas 图形库

    1.github地址: https://github.com/fabricjs/fabric.js 2.简述 Fabric.js将canvas的编程变得简单.同时在canvas上添加了交互.交互包括: ...

  7. MySQL8新特性(2)--mysql的升级过程

    在之前的版本中,安装新的版本mysql之后,mysql server在下一次启动时,会自动升级数据字典表,然后dba需要执行mysql_upgrade手动升级mysql schema中的系统表,以及其 ...

  8. XNOR-Net:二值化卷积神经网络

    https://www.jianshu.com/p/f9b015cc4514 https://github.com/hpi-xnor/BMXNet  BMXNet:基于MXNet的开源二值神经网络实现 ...

  9. IDEA查看接口的实现类

    查找接口的实现类: 快捷键 ctrl + alt +B 再按F2查看详细文档注解 查看类或接口的继承关系: ctrl + h

  10. Shenzhen Wanze Technology Co., Ltd.技术支持

    本网页为Shenzhen Wanze Technology Co., Ltd.团队的技术支持网址,如果在我们开发的游戏中遇到任何问题,欢迎联系我们! QQ:2535510006 邮箱:25355100 ...