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

模型绑定(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: Homepublic 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 id  = 1)

 绑定复杂类型

当动作方法的参数是复合类型时,DefaultModelBinder类将用反射来获取public属性集。

在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: Homepublic ActionResult Index(int? id  = 1){Person dataItem = personData.Where(p => p.PersonId == id).First();return View(dataItem);}public ActionResult CreatePerson(){return View(new Person());}[HttpPost]public ActionResult CreatePerson(Person model){return View("Index",model);}}

为没有参数的CreatePerson控制器方法创建一个对应的视图:CreatePerson.cshtml ,代码如下图所示:

@model MvcModels.Models.Person
@{ViewBag.Title = "CreatePerson";Layout = "~/Views/Shared/_Layout.cshtml";
}<h2>CreatePerson</h2>
@using (Html.BeginForm())
{<div>@Html.LabelFor(m => m.PersonId) @Html.EditorFor(m => m.PersonId)</div><div>@Html.LabelFor(m => m.FirstName) @Html.EditorFor(m => m.FirstName)</div><div>@Html.LabelFor(m => m.LastName) @Html.EditorFor(m => m.LastName)</div><div>@Html.LabelFor(m => m.Role) @Html.EditorFor(m => m.Role)</div><button type="submit">Submit</button>
}

运行导航到/Home/CreatePerson,结果如下图所示:

          

点击submit按钮后,可以看到已经将输入的数据  传到 Index 界面了:

         

 

在表单传递给CreatePerson方法时,形成了一种不同的模型绑定情况。默认的模型绑定器发现,动作方法需要一个Person对象,于是会依次处理每个属性。 对于每个简单类型的属性,绑定器会视图查找请求中的一个值,就如同上一个示例所做的那样。因此,当遇到 PersonId属性时,绑定器会查找personId的数据值,它将在请求的表单中发现这个值。

如果一个属性需要另一个复合类型,那么,该过程会针对新类型重复执行。获取该类型的public属性集,而绑定器会视图找出这些属性的值。不同的是,这些属性是嵌套的。例如,Person类的HomeAddress 属性 是Address类型。


创建易于绑定的HTML

更新CreatePerson.cshtml中的代码,以便为Address类型捕获一些属性:

@model MvcModels.Models.Person
@{ViewBag.Title = "CreatePerson";Layout = "~/Views/Shared/_Layout.cshtml";
}<h2>CreatePerson</h2>
@using (Html.BeginForm())
{<div>@Html.LabelFor(m => m.PersonId) @Html.EditorFor(m => m.PersonId)</div><div>@Html.LabelFor(m => m.FirstName) @Html.EditorFor(m => m.FirstName)</div><div>@Html.LabelFor(m => m.LastName) @Html.EditorFor(m => m.LastName)</div><div>@Html.LabelFor(m => m.Role) @Html.EditorFor(m => m.Role)</div><div>@Html.LabelFor(m => m.HomeAddress.City)@Html.EditorFor(m => m.HomeAddress.City)</div><div>@Html.LabelFor(m => m.HomeAddress.Country)@Html.EditorFor(m => m.HomeAddress.Country)</div><button type="submit">Submit</button>
}

更新Index.html中的代码,如下图所示: 


@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><div><label>City:</label>@Html.DisplayFor(m => m.HomeAddress.City)</div>
<div><label>County:</label>@Html.DisplayFor(m => m.HomeAddress.Country)</div>

运行导航到/Home/CreatePerson,如下图所示:

           

点击Submit按钮后,数据传递成功,情况如下:

             

简而言之,模型绑定器查找的是 HomeAddress.Country,即,模型对象的属性名(HomeAddress)与属性类型(Address)d的属性名(Country)的组合。 


指定自定义前缀 

偶尔有些时候,生成的HTML与一种类型的对象有关,但是希望绑定到另一个对象。这意味着包含的前缀与模型绑定器期望的结构不对应。这个时候需要用到属性注解了。

Models文件夹中创建了一个新的类文件,名称为AddressSummary.cs,如下图所示:

    public class AddressSummary{public string City { get; set; }public string Country { get; set; }}

Home控制器中增加一个动作方法,如下图所示: 

        public ActionResult DisplaySummary(AddressSummary summary){return View(summary);}

修改CreatePerson.cshtml文件中表达提交的目标:

@model MvcModels.Models.Person
@{ViewBag.Title = "CreatePerson";Layout = "~/Views/Shared/_Layout.cshtml";
}<h2>CreatePerson</h2>
@using (Html.BeginForm("DisplaySummary","Home"))
{<div>@Html.LabelFor(m => m.PersonId) @Html.EditorFor(m => m.PersonId)</div><div>@Html.LabelFor(m => m.FirstName) @Html.EditorFor(m => m.FirstName)</div><div>@Html.LabelFor(m => m.LastName) @Html.EditorFor(m => m.LastName)</div><div>@Html.LabelFor(m => m.Role) @Html.EditorFor(m => m.Role)</div><div>@Html.LabelFor(m => m.HomeAddress.City)@Html.EditorFor(m => m.HomeAddress.City)</div><div>@Html.LabelFor(m => m.HomeAddress.Country)@Html.EditorFor(m => m.HomeAddress.Country)</div><button type="submit">Submit</button>
}

导航到/Home/CreatePerson方法: 

           

点击submit方法后,结果如下图所示: 

            

 由于Country和City的前缀改变了,由HomeAddress变成了AddressSummary,故绑定器无法实现绑定。只需对动作方法的参数运用Bind注解属性即可,代码如下图所示:

public ActionResult DisplaySummary([Bind(Prefix ="HomeAddress")]AddressSummary summary)
{return View(summary);
}

重新运行代码,即可看到运行成功: 

                


有选择性的绑定属性 

如果希望对某一属性不需要模型绑定器进行绑定,可以使用如下代码:

public ActionResult DisplaySummary([Bind(Prefix ="HomeAddress",Exclude ="Country")]AddressSummary summary)
{return View(summary);
}

也可以设置模型绑定器只绑定某一属性,代码如下图所示:

    [Bind(Include ="City")]public class AddressSummary{public string City { get; set; }public string Country { get; set; }}

 


绑定到数组

默认模型绑定器的一个雅致的特性是它支持动作方法参数作为数组。在Home控制器中添加一个方法,如下图所示:

        public ActionResult Names(string[] names){names = names ?? new string[0];return View(names);}

创建Names方法对应的视图Names.csthml,如下图所示: 

@model string[]
@{ViewBag.Title = "Names";Layout = "~/Views/Shared/_Layout.cshtml";
}<h2>Names</h2>
@if (Model.Length == 0)
{using (Html.BeginForm()) {for (int i = 0; i < 3; i++){<div><label>@(i + 1):</label>@Html.TextBox("names")</div>}<button type="submit">Submit</button>}
}
else
{foreach (string str in Model){<p>@str</p>}@Html.ActionLink("Back", "Names")
}

导航到/Home/Names,如下图所示:

           

点击Submit后,如下图所示: 

          

递交表单时,默认的模型绑定器明白动作方法需要一个字符串数组。于是会查找与参数具有同样名称的数据项。在本例中,意味着会将所有input元素的内容聚集到一起用以填充数组。 

 

 


绑定到集合 

能绑定的不仅仅是数组,还可以使用.Net集合类。

修改names动作方法为强类型集合,如下图所示:

        public ActionResult Names(IList<string> names){names = names ?? new List<string>();return View(names);}

并修改Names.cshtml页面代码,如下所示:

@model IList<string>
@{ViewBag.Title = "Names";Layout = "~/Views/Shared/_Layout.cshtml";
}<h2>Names</h2>
@if (Model.Count() == 0)
{using (Html.BeginForm()) {for (int i = 0; i < 3; i++){<div><label>@(i + 1):</label>@Html.TextBox("names")</div>}<button type="submit">Submit</button>}
}
else
{foreach (string str in Model){<p>@str</p>}@Html.ActionLink("Back", "Names")
}

运行结果如下图所示:

            

点击提交后: 


绑定到自定义模型集合 

可以将一些单个的数据属性绑定成一个自定义类型的数组。如上述的AddressSummary模型类.

在控制器中增加一个新的动作方法,如下图所示:

        public ActionResult Address(IList<AddressSummary> addresses){addresses = addresses ?? new List<AddressSummary>();return View(addresses);}

添加Address动作方法对应的页面,代码如下图所示:

@using MvcModels.Models
@model IList<AddressSummary>
@{ViewBag.Title = "Address";Layout = "~/Views/Shared/_Layout.cshtml";
}<h2>Address</h2>
@if (Model.Count() == 0)
{using (Html.BeginForm()){for (int i = 0; i < 3; i++){<fieldset><legend>Address @(i + 1)</legend><div><label>City:</label>@Html.Editor("[" + i + "].City")</div><div><label>Country:</label>@Html.Editor("[" + i + "].Country")</div></fieldset>}<button type="submit">Submit</button>}
}
else
{foreach (AddressSummary str in Model){<p> @str.City, @str.Country</p>}@Html.ActionLink("Back","Address");
}

 导航到/Home/Address,并输入内容,页面如下图所示:

               

点击提交后,正确显示页面:

              

可以看到生成的HTML代码: 

      

 

当表单被提交时,默认的模型绑定器知道它需要创建的是一个AddressSummary对象集合,并利用 name 标签属性中的数组索引前缀获取对象的类型。以【0】为前缀的那些属性表示一个AddressSummary对象,以【1】为前缀表示第二个对象。以此类推。 


手工调用模型绑定

当动作方法定义了参数时,模型绑定过程是自动执行的,但是只要你愿意,也可以直接控制这一过程。如下将演示如何将Home控制器的Address动作方法修改成手动调用绑定过程。

修改Address方法,代码如下图所示:

        public ActionResult Address(IList<AddressSummary> addresses){addresses = addresses ?? new List<AddressSummary>();UpdateModel(addresses);return View(addresses);}

UpdataModel方法以上一条语句定义的时候的模型对象为参数,并试图用标准的绑定该过程来获取其public属性的值。 

当手工调用绑定时,可以将绑定过程限制到单一的数据源。默认情况下,绑定器会搜索四个地方:表单数据、路由数据、查询字符串,以及上传文件。一下代码演示了如何将绑定器限制到搜索单一位置的数据——表单数据。

        public ActionResult Address(IList<AddressSummary> addresses){addresses = addresses ?? new List<AddressSummary>();UpdateModel(addresses,new FormValueProvider(ControllerContext));return View(addresses);}

UpdateModel方法的这一版本以IValueProvider接口的一个实现为参数,该实现也成为了绑定过程的唯一的数据源。四个默认的数据位置的每一个都由一个IValueProvider实现表示:

内建的IValueProvider
IValueProvider
Request.FormFormValueProvider
RouteData.ValueRouteDataValueProvider
Request.QueryStringQueryStringValueProvider
Request.FilesHttpFileCollectionValueProvider

可以用另一种跟优雅的写法来表示:

        public ActionResult Address(FormCollection formData){List<AddressSummary> addresses = new List<AddressSummary>();UpdateModel(addresses,formData);return View(addresses);}

 处理绑定错误

用户难免会提供一些不能绑定到相应模型属性的值,需要对这些情况抛出些异常。特别是使用UpdateModel方法时,必须做好捕捉该异常的准备,代码如下图所示:

        public ActionResult Address(FormCollection formData){List<AddressSummary> addresses = new List<AddressSummary>();try{UpdateModel(addresses, formData);}catch (InvalidCastException ex){//给用户提供反馈}return View(addresses);}

另一个可选的办法是,可以使用TryUpdateModel方法。如果模型绑定成功,返回ture;否则返回false;

        public ActionResult Address(FormCollection formData){List<AddressSummary> addresses = new List<AddressSummary>();if (TryUpdateModel(addresses,formData)){//正常处理}else{//给用户提供反馈}return View(addresses);}

这两种方式的唯一区别是,你是否喜欢捕捉并处理异常。 


定制模型绑定系统

还有一些不同的方式,可以对绑定系统进行定制。

通过定义一个自定义的值提供器,可以将自己的数据源添加到模型绑定过程。值提供器(Valueprovider)需要实现IValueProvider接口,如下图所示:

public interface IValueProvider{bool ContainsPrefix(string prefix);ValueProviderResult GetValue(string key);}

ContainsPrefix方法由模型绑定器调用,以确定这个值提供器是否可以解析给定前缀的数据。

GetValue方法返回给定数据键的值,或者在提供器无法得到合适的数据时返回null。

新建一个CountryValueProvider类,实现以上接口:

public class CountryValueProvider : IValueProvider{public bool ContainsPrefix(string prefix){return prefix.ToLower().IndexOf("country") > -1;}public ValueProviderResult GetValue(string key){if (ContainsPrefix(key)){return new ValueProviderResult("USA", "USA", CultureInfo.InvariantCulture);}else{return null;}}}

该值提供器只对请求Country属性的值进行响应,而且总是返回 USA 。对于其他请求,返回 NULL,表示无法提供数据。

返回值必须提供一个ValueProviderResult类来返回。这个类有三个构造器参数:第一个参数是与请求键关联的数据项,第二个参数是作为HTML页面一部分的该数据的安全显示形式,第三个参数是该值相关的文化信息。这里已经指定为了InvariantCulture

为了在应用程序中对这个值进行注册,需要一个工厂类,以便在MVC框架需要时为这个提供器创建实例。这个工厂类必须派生于抽象类ValueProviderFactory。代码如下图所示:

public class CustomValueProviderFactory : System.Web.Mvc.ValueProviderFactory
{public override IValueProvider GetValueProvider(ControllerContext controllerContext){return new CountryValueProvider();}
}

 当模型绑定器要为绑定过程获取值时,会调用这个GetValueProvider方法。上述实现了简单的创建并返回了CurrentTimeProvider类的一个实例,但你可以使用ControllerContext参数提供的数据,以便创建不同的值提供器,对不同种类的请求进行响应。

然后在Global.asax的Application_Start方法中注册:

        protected void Application_Start(){AreaRegistration.RegisterAllAreas();RouteConfig.RegisterRoutes(RouteTable.Routes);ValueProviderFactories.Factories.Insert(0,new CustomValueProviderFactory());}

如果希望这一提供器在其他提供器不能提供数据值时作为一个备选,那么可以用Add方法把工厂追加到集合末尾: 

ValueProviderFactories.Factories.Add(new CustomValueProviderFactory());

运行程序,导航到/Home/Address,如下图所示:

            

点击Submit,如下图所示:

            


 创建自定义模板绑定器

通过创建一个特定类型的自定义模型绑定器,可以覆盖默认绑定器的行为。自定义模型绑定器需要实现IModelBinder接口。创建一个AddressSummaryBinder.cs类文件,如下图所示:

    public class AddressSummaryBinder : IModelBinder{public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext){AddressSummary model = (AddressSummary)bindingContext.Model ?? new AddressSummary();model.City = GetValue(bindingContext,"City");model.Country = GetValue(bindingContext,"Country");return model;}private string GetValue(ModelBindingContext context,string name){name = (context.ModelName == "" ? "" : context.ModelName + ".") + name;ValueProviderResult result = context.ValueProvider.GetValue(name);if (result == null || result.AttemptedValue == ""){return "<Not Specified>";}else{return (string)result.AttemptedValue;}}}

BindModel方法的参数是一个ControllerContext对象,可以用它来访问当前请求的细节。另一个是ModelBindingContext对象,该对象提供了当前寻找的模型对象的细节,并能访问MVC应用程序中其他模型绑定工具。 

ModelBindingContext类所定义的最有用的属性
属性描述
Model如果手工调用了绑定,可返回传递给UpdataModel方法的模型对象
ModelName返回被绑定模型的名称
ModelType返回被创建模型的类型
ValueProvider返回能用于请求中获得数据值的IValueProvider实现

在调用BindModel方法时,检查已经是否设置了 ModelBindingContext 对象 的Model属性,如果已经设置,则该模型便是将要为之生成数据值的对象,如没有设置,则创建AddressSummary类的一个实例。通过调用GetValue方法获取City和Country属性的值,然后返回已经过填充的AddressSummary对象。

在GetValue方法中,通过了ModelBindingContext.ValueProvider属性获得的IValueProvider实现,以获取模型对象属性的值。

ModelName属性能够告诉我们,对正在寻找的属性的名称,是否需要追加一个前缀。当无法为一个属性找到值,或者该属性为空字符串时,便提供一个默认值<Not Specified>.

 

然后在Global.asax的Application_Start方法中注册该模型绑定器:

        protected void Application_Start(){AreaRegistration.RegisterAllAreas();RouteConfig.RegisterRoutes(RouteTable.Routes);ModelBinders.Binders.Add(typeof(AddressSummary), new AddressSummaryBinder());}

导航到/Home/Address,并输入内容,如下图所示: 

                 

提交后,结构如下图所示: 

                   

 


 用注解属性注册模型绑定器

可以在模型类上使用ModelBinder注解属性进行修饰,来注册自定义模型绑定器。不必使用Global.asax文件。如下图所示:

    [ModelBinder(typeof(AddressSummaryBinder))]public class AddressSummary{public string City { get; set; }public string Country { get; set; }}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

精通ASP.NET MVC ——模型验证

文章内容较长&#xff0c;用于记录自己学习。模型验证&#xff08;Model Vaildation&#xff09;是确保应用程序所接受的数据适合于绑定到模型&#xff0c;并且在不合适时给用户提供有用的信息&#xff0c;以帮助他们修正问题的过程。 准备示例项目 新建一个空的MVC项目&…

[wbia 2.2] 对检索结果进行评估

评估对检索系统的性能&#xff1a; 由于我们这里的检索结果&#xff0c;是主要根据PageRank的排名&#xff0c;以及Lucene对文本的分词和相关性计算的最后得分&#xff0c;进行权值调整后得到的排名结果。 这里对我们检索系统的进行性能评估&#xff0c;这里主要评估的是检索结…

错误175:具有固定名称MySql.Data.MySqlClient的ADO.NET提供程序未在计算机或者应用程序配置文件中注册或者无法加载

背景&#xff1a; EF连接MySQL时报错&#xff0c;截图如下图所示&#xff1a; 网上翻阅了很多资料&#xff0c;感觉有一篇文章说的比较靠谱&#xff1a;点击阅读。解决问题的大致过程如下&#xff1a; 在尝试使用MySQL&#xff0c;ADO.NET&#xff08;数据库优先&#xff09;和…

精通ASP.NET MVC ——URL和Ajax辅助器方法

Ajax(或者&#xff0c;如果你愿意&#xff0c;也可以称为AJAX)是 Asynchronous JavaScripts and XML(异步JavaScripts与XML)。其XML部分并不如它往常那样意义重大&#xff0c;但是异步部分却使AJax十分有用。这是后台请求服务器数据&#xff0c;而不必重载Web页面的一种模型。M…

精通ASP.NET MVC ——控制器可扩展性

MVC中引导动作方法执行过程的请求流程管道中&#xff0c;有两个重要的部件&#xff1a;控制器工厂(Controller Factory) 和 动作调用器&#xff08;Action Invoker&#xff09;。控制器工厂负责创建对请求进行服务的控制器实例&#xff0c;动作调用器负责查找并调用控制器类中的…

永中向香港博览会主办方演示云办公(转载)

4月16号“香港国际资讯博览会”主办方香港贸发局对永中云办公产品非常感兴趣&#xff0c;由永中员工演示&#xff0c;并拍摄了演示视频。转载于:https://blog.51cto.com/premium/837675

Backbone.js学习笔记

为什么80%的码农都做不了架构师&#xff1f;>>> http://documentcloud.github.com/backbone var todoItem new TodoItem(); todoItem.url /todo; todoItem.fetch(); todoItem.get(description)var TodoItem Backbone.Model.extend({urlRoot: /todos }); var tod…

ASP.NET MVC中使用Autofac实现简单依赖注入

本文参考资料&#xff1a; 1、https://www.cnblogs.com/RayWang/p/11128554.html。 2、https://www.cnblogs.com/eedc/p/6127181.html 3、https://www.cnblogs.com/ancupofcoffee/p/5007649.html#top 前言 关于IoC和DI(依赖注入)的概念网上一搜一大把。简单来说&#xff0c;Io…

初探EntityFramework——来自数据库的EF设计器

本文通过简单的示例&#xff0c;先初步了解下EF四种设计模式之一&#xff1a;来自数据库的EF设计器。 来自数据库的EF设计器&#xff0c;顾名思义&#xff0c;需要有新建的数据库和表结构&#xff0c;才能生成EF设计器&#xff0c; 在本地新建数据库KTStore&#xff0c;并且新建…

初探EntityFramework——空EF设计器模型

如果没有任何现存数据库架构&#xff0c;可以使用空的EF设计器模型。本文将通过简单示例&#xff0c;了解如何使用空EF设计器模型。 新建空的控制器应用程序EFDesignerDemo&#xff0c;如下图所示&#xff1a; 在项目中右键&#xff0c;选择“添加”&#xff0c;然后是“新建项…

初探EntityFramework——来自数据库的Code First

Entity Framkwork从第二版&#xff08;EF4&#xff09;开始&#xff0c;支持新的CodeFirst模式&#xff08;程序代码优先&#xff09;&#xff0c;以自定义类定义数据模型。简化了EF的开发过程。本文章使用简单的示例来说明如何使用来自数据库的CodeFirst模式。 新建一个空的控…

初探EntityFramework——空Code First模型

如果不是从现有的系统升级&#xff0c;想要创建全新的项目可以从“空Code First模型开始”。“空CodeFirst模型”要先创建类&#xff0c;Visual Studio会从项目第一次执行的时候根据连接自动创建需要的数据库结构。本文将简单示例说明如何使用“空CodeFirst模型”。 新建控制台…

初探EntityFramework——实体类结构映射

实体类与数据表的映射有一套专用的规则。Code First 采用的惯例优于预先设置的设计&#xff0c;在没有任何设置的情况下&#xff0c;自动检测模型结构并推导出默认设置以简化类的设计&#xff0c;因此不需要特别设置类的属性即可完成模型设计。 例如&#xff0c;当DbContext的模…

深入了解EntityFramework——数据注解属性

当惯例规则不符合设计需求时&#xff0c;我们可以使用数据注解配置打造更合适的数据库模型。本文根据示例项目对常用的数据注解属性做一个简要的举例说明。 EFCodeFirst使用的约定大于配置的的编程模式&#xff0c; 这种模式利用默认约定根据我们的领域模型建立概念模型。然我们…

Android上实现柱状图表

Android上实现柱状图算法实现 第一步&#xff1a; 获取Android设备的屏幕大小 第二步&#xff1a; 在View对象中使用Canvas绘制蓝色边框与白色背景XY轴两条线&#xff0c;代码如下 第三步&#xff1a; 绘制柱状图标题 第四步&#xff1a; 根据数据集计算出每个系列数据所占X轴的…

深入了解EntityFramework——Fluent API

Fluent API 除了惯例原则与属性数据注解外&#xff0c;FluentAPI是另一种支持实体类配置设置的方式。与属性数据注解相比&#xff0c;它提供了更广泛的功能与设置弹性。实体类若同时设置了数据注解&#xff0c;则采用的优先权是“Fluent API” > "数据注解" &g…

深入了解EntityFramework——Lazy Loading与Eager Loading

Lazy Loading&#xff1a;延迟加载。Eager Loading&#xff1a;贪婪加载。 首先通过一个简单的控制台应用程序例子说明延迟加载&#xff1a; 订单主表和订单从表&#xff0c;并且订单主表和订单从表是一对多的关系&#xff0c;代码如下图所示&#xff1a; //订单主表public cl…

SQL – 2.SQLServer的管理 + 3.SQL基础1 + 4.SQL基础2

SQLServer的管理 常用字段类型&#xff1a;bit(可选值0、1)、datetime、int、varchar、nvarchar&#xff08;可能含有中文用nvarchar&#xff09;varchar、nvarchar 和char(n)的区别&#xff1a; char(n)不足长度n的部分用空格填充。Var&#xff1a;Variable&#xff0c;可变的…

EntityFramework进阶——继承

通过类型继承&#xff0c;我们可以更弹性地处理数据&#xff0c;有3中相关的技巧&#xff0c;即TPH&#xff0c;TPT&#xff0c;TPC。 Table Per Hierarchy&#xff08;TPH&#xff09; 当单个数据表存储不同数据类型时&#xff0c;在数据模型的设计上&#xff0c;可以使用Tab…

EntityFramework进阶——数据编辑与维护

实体数据对象状态 在EF环境下&#xff0c;应用程序更改数据对象会引发数据集状态的变更&#xff0c;可能的状态有以下几种&#xff1a; 数据对象状态列表Added添加实体对象创建到实体集中&#xff0c;数据未添加进数据库Modified实体对象已经存在于实体数据集中&#xff0c;数…