• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
PowerCoder
博客园    首页    新随笔    联系   管理    订阅  订阅

ASP.NET Core MVC 模型绑定 (转载)

ASP.NET Core MVC的Model Binding会将HTTP Request数据,以映射的方式对应到参数中。基本上跟ASP.NET MVC差不多,但能Binding的来源更多了一些。
本篇将介绍ASP.NET Core的Model Binding。

 

Model Binding



要接收Client 传送来的数据,可以通过Action 的参数接收,如下:

using Microsoft.AspNetCore.Mvc;
 
namespace MyWebsite.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index(int id)
        {
            return Content($"id: {id}");
        }
    }
}

id就是从HTTP Request的内容被Binding的Model参数。
预设的Model Binding会从HTTP Request的三个地方取值(优先顺序由上到下):

 

  • Form

透过HTTP POST的form取值。如下图:

 

  • Route

是通过MVC Route URL取值。
如:http://localhost:5000/Home/Index/2,id取出的值就会是2。

 

  • Query

是通过URL Query参数取值。
如:http://localhost:5000/Home/Index?id=1,id取出的值就会是1。

 

如果三者都传入的话,会依照优先顺序取值Form > Route > Query。

 

 

Binding Attributes



除了预设的三种Binding 来源外,还可以通过Model Binding Attributes 从HTTP Request 的其他数据中Binding。有以下6 种:

  • [FromHeader]

从HTTP Header取值。

 

  • [FromForm]

通过HTTP POST的form取值。

 

  • [FromRoute]

是通过MVC Route URL取值。

 

  • [FromQuery]

是通过URL Query参数取值。

 

  • [FromBody]

从HTTP Body取值,通常用于取JSON, XML。
ASP.NET Core MVC预设的序列化是使用JSON,如果要传XML格式做Model Binding的话,要在MVC服务加入XmlSerializerFormatters,如下:

Startup.cs

// ...
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
            .AddXmlSerializerFormatters();
}

 

  • [FromServices]

这个比较特别,不是从HTTP Request取值,而是从DI容器取值。
DI预设是使用Constructor Injection,但Controller可能会因为每个Action用到不一样的Service导致很多参数,所以也可以在Action注入Service。

 

 

范例程序


 

// ...
public class HomeController : Controller
{
    public IActionResult FirstSample(
        [FromHeader]string header,
        [FromForm]string form,
        [FromRoute]string id,
        [FromQuery]string query)
    {
        return Content($"header: {header}, form: {form}, id: {id}, query: {query}");
    }
     
    public IActionResult DISample([FromServices] ILogger<HomeController> logger)
    {
        return Content($"logger is null: {logger == null}.");
    }
 
    public IActionResult BodySample([FromBody]UserModel model)
    {
        return Ok(model);
    }
}
 
// ...
public class UserModel
{
    public int Id { get; set; }       
    public string Name { get; set; }       
    public string Email { get; set; }       
    public string PhoneNumber { get; set; }       
    public string Address { get; set; }
}

 

输出结果

FirstSample输出结果:

 

DISample输出结果:
http://localhost:5000/Home/DISample

logger is null: False.

 

BodySample输出结果:

  • JSON

 

  • XML

 

 

Model 验证



Model Binding 也可以顺便帮忙验证字段数据,只要在字段的属性上面带上Validation Attributes,如下:

using System.ComponentModel.DataAnnotations;
// ...
public class UserModel
{
    [Required]
    public int Id { get; set; }
 
    [RegularExpression(@"\w+")]
    [StringLength(20, MinimumLength = 4)]
    public string Name { get; set; }
 
    [EmailAddress]
    public string Email { get; set; }
 
    [Phone]
    public string PhoneNumber { get; set; }
 
    [StringLength(200)]
    public string Address { get; set; }
}

然后在Action 加上判断:

Controllers\HomeController.cs

using Microsoft.AspNetCore.Mvc;
 
namespace MyWebsite.Controllers
{
    public class HomeController : Controller
    {
        // ...
        public IActionResult BodySample([FromBody]UserModel model)
        {
            // 由于 Id 是 int 类型,int 默认为 0
            // 虽然带上了 [Required],但不是 null 所以算是有值。
            if (model.Id < 1)
            {
                ModelState.AddModelError("Id", "Id not exist");
            }
            if (ModelState.IsValid)
            {
                return Ok(model);
            }
            return BadRequest(ModelState);
        }
    }
}

输入错误数据的输出结果:

.NET Core提供了很多的Validation Attributes,可以参考官网:

System.ComponentModel.DataAnnotations Namespace

 

 

自定义Validation Attributes



如果.NET Core提供的Validation Attributes不够用还可以自己做。
例如上述范例的数据模型多了生日字段,需要验证年龄:

using System;
using System.ComponentModel.DataAnnotations;
 
namespace MyWebsite.Attributes
{
    public class AgeCheckAttribute : ValidationAttribute
    {
        public int MinimumAge { get; private set; }
        public int MaximumAge { get; private set; }
 
        public AgeCheckAttribute(int minimumAge, int maximumAge)
        {
            MinimumAge = minimumAge;
            MaximumAge = maximumAge;
        }
 
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var date = Convert.ToDateTime(value);
 
            if (date.AddYears(MinimumAge) > DateTime.Today
                || date.AddYears(MaximumAge) < DateTime.Today)
            {
                return new ValidationResult(GetErrorMessage(validationContext));
            }
 
            return ValidationResult.Success;
        }
 
        private string GetErrorMessage(ValidationContext validationContext)
        {
            // 有帶 ErrorMessage 的话优先使用
            // [AgeCheck(18, 120, ErrorMessage="xxx")]
            if (!string.IsNullOrEmpty(this.ErrorMessage))
            {
                return this.ErrorMessage;
            }
 
            // 自定义错误信息
            return $"{validationContext.DisplayName} can't be in future";
        }
    }
}

 

 

参考



Overview of ASP.NET Core MVC
Introduction to model validation in ASP.NET Core MVC
ASP.NET CORE 2.0 MVC MODEL BINDING
ASP.NET CORE 2.0 MVC MODEL VALIDATION

 

Model Binding in ASP.NET Core

上面的微软文档这里介绍了,ASP.NET Core中模型绑定的各种[FromXXX]特性,这些特性类都有一个Name属性,如果Http请求(例如Header,Body,URL参数等)中的字段名和 模型的属性名/Action方法的参数名 不一样,可以用特性类的Name属性来指定从Http请求的哪个字段来绑定 模型的属性/Action方法的参数。例如下面的示例演示了,用Http请求Header中的Accept-Language字段来给Action方法OnGet的参数language赋值:

public void OnGet([FromHeader(Name = "Accept-Language")] string language)

 

原文链接

 

posted @ 2018-12-21 16:56  PowerCoder  阅读(1288)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3