精通ASP.NET MVC ——模型绑定

本文详细介绍了ASP.NET MVC中的模型绑定概念,包括如何使用默认模型绑定器、处理复杂类型、创建易于绑定的HTML、指定自定义前缀、有选择性绑定、绑定到数组和集合等。通过示例代码展示了模型绑定的工作原理和应用场景,帮助开发者更好地理解和掌握模型绑定机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模型绑定(Model Binding)是指,用浏览器以Http请求方式发送的数据来创建.Net对象的过程。

准备示例项目 

新建一个空的MVC项目,名叫MvcModels,接下去会以此项目来演示各种功能。

Models文件夹中创建一个Person.cs类文件,代码如下图所示:

namespace MvcModels.Models
{
    public class Person
    {
        public int PersonId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
        public Address HomeAddress { get; set; }
        public bool IsApproved { get; set; }
        public Role Role { get; set; }
    }

    public class Address
    {
        public string Line1 { get; set; }
        public string Line2 { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
    }

    public enum Role
    {
        Admin,
        User,
        Guest
    }
}

定义一个Home控制器,代码如下图所示:

    public class HomeController : Controller
    {
        private Person[] personData = {
            new Person { PersonId = 1,FirstName = "Adam",LastName = "Freeman" },
            new Person { PersonId = 2,FirstName = "Jacqui",LastName = "Griffyth"},
            new Person { PersonId = 3,FirstName = "John",LastName = "Smith" },
            new Person { PersonId = 4,FirstName = "Anne",LastName = "Jones"}
        };
        // GET: Home
        public ActionResult Index(int id)
        {
            Person dataItem = personData.Where(p => p.PersonId == id).First();
            return View(dataItem);
        }
    }

新增Index控制器对应的Index.cshtml页面,代码如下: 

@model MvcModels.Models.Person

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Person</h2>
<div><label>ID:</label> @Html.DisplayFor(m => m.PersonId)</div>
<div><label>First Name:</label>@Html.DisplayFor(m => m.FirstName)</div>
<div><label>Last Name:</label>@Html.DisplayFor(m => m.LastName)</div>
<div><label>Roles:</label>@Html.DisplayFor(m => m.Role)</div>

新增_layout.cshtml布局页面,代码如下: 

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <style>
        label {
            display:inline-block; width:100px;font-weight:bold;margin:5px;
        }
        form label {
            float:left;
        }
        input.text-box {
            float:left;margin:5px
        }
        button[type=submit] {
            margin-top:5px;
            float:left;
            clear:left;
        }
        form div {
            clear:both;
        }
    </style>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

运行程序,并导航到/Home/Index/1,结果如下图所示: 

               

默认的动作绑定器ControllerActionInvoker要依靠模型绑定器来生成调用动作所需的数据对象。模型绑定器IModelBinder接口所定义,接口如下图所示:

public interface IModelBinder
{
    object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
}

在一个MVC应用程序中,可以有多个模型绑定器,而每个绑定器可以负责绑定一个或者多个模型类型。它会考察该方法所定义的参数,并查找各个参数类型所依赖的模型绑定器。

在上述示例中,动作调用器会检查Index方法,并发现它具有一个int型的参数。于是会查找负责int值绑定的绑定器,并调用BindModel方法。


使用默认的模型绑定器

虽然程序可以定义自定义的模型绑定器,大多数程序都是依靠内建的模型绑定器DefaultModelBinder.当动作调用器找不到绑定某个类型的自定义绑定器时,这个默认的模型绑定器便是由动作调用器所使用的一个绑定器。默认情况下,这个模型绑定器会搜索四个位置:

DefaultModelBinder类查找参数数据的顺序
描述
Request.Form 由用户在HTML的form(表单)元素中提供的值
RouteData.Values 用应用程序路由获得的值
Request.QueryString 包含在请求URL中的查询字符串部分的数据
Request.Files 请求中上传的文件

这些位置被依序搜索。例如,在上述简单示例中,DefaultModelBinder会为id参数查找以下的一个值:

1、Request.Form["id"]

2、RouteData.Values["id"]

3、Request.QueryString["id"]

4、Request.Files["id"]

只要找到值,便会停止搜索。在上述例子中,搜索到第二步就停了,不会到第三步。

当处理简单参数类型时,DefaultModelBinder会尝试使用 System.ComponentModel.TypeDescriptor类。将已经从请求数据获得的字符串值转化成参数类型。如果无法转为这个值:例如给int值传一个“apple”,程序就会报错:

解决这个问题有两种办法:

一、在动作方法参数中设置可空类型(nullable),这为绑定器提供一个退路,一个可空的int参数可以不必为数字值,这让模型绑定器在调用动作时,这可以让动作方法参数设置为Null。

public ActionResult Index(int? id)

二、 在动作方法中运用默认值,当模型绑定器无法为id参数找到一个值时,将默认值1来代替,如下所示:

 public ActionResult Index(int
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值