(推荐)第15章 扩展ASP.NET MVC (IModelBinder、过滤器)
2017-11-11 10:54
381 查看
Authorization [ˌɔ:θərəˈzeɪʃn] 授权
模型绑定的过程分为两个阶段:
通过使用值提供器理解数据的来源
使用这些值创建/更新模型对象(通过使用模型绑定器)
(1)、使用值提供器解析请求数据
值提供器:访问能够在模型绑定过程中正确使用的信息。
ASP.NET MVC中默认模型绑定器可以对传统类、集合类、列表、数组甚至字典进行模型绑定。
不支持不可变对象,对象的初始值必须通过构造函数设置,之后不能改变。
当创建一个新的模型绑定器时,我们需要告知ASP.NET MVC框架存在一个新的模型绑定器以及何时使用它。
可以使用[ModelBinder]特性来装饰绑定类,也可以在ModelBinders.Binders的全局列表中注册新的模型绑定器。
效果:
效果:
https://www.cnblogs.com/SkySoot/p/6050251.html
Asp.net MVC的Model Binder工作流程以及扩展方法(1) - Custom Model Binder
ASP.NET MVC支持通过应用于类和属性的特性所表示的模型元数据。
这些特性主要包含在System.ComponetModel(.NET 1.0中引入)和System.ComponetModel.DataAnnotations(.NET 3.5 SP1和ASP.NET Dynamic Data一起被引入)中。
实现一个元数据提供器意味着需要继承类ModelMetadataProvider,并实现其中的3个抽象方法:
A. GetMetadataForType 返回关于整个类的元数据。
B. GetMetadataForProperty 返回类上单个属性的元数据。
C. GetMetadataForProperties 返回类上所有属性的元数据。
还有一个名为AssociatedMetadataProvider的派生类,可以被计划通过特性提供元数据的元数据提供器使用。它把上述三个方法的调用压缩到对CreateMetadata方法的调用,并传递附加到模型和模型属性的特性列表。由于简化了API和对元数据“兄弟类”的自动支持,因此如果要编写用特性装饰模型的元数据提供器,那么使用AssociatedMetadataProvider作为提供器的基类就是一个不错的选择。
https://book.2cto.com/201301/13269.html
ModelValidatorProviders.Providers.Add
ASP.NET MVC默认安装了两个视图引擎:即在MVC 1.0中的WebForms视图引擎和Razor视图引擎(MVC3)。
ASP.NET MVC第三方视图引擎包括Spark、NHaml和NVelocity等。
1 、自定义视图引擎
2、 编写HTML辅助方法
3、 编写Razor辅助方法
使用:注意不能通过地址使用 http://localhost:4405/index/B
示例2:Action方法名以Product-开头
有些类实现了该接口,其中包括[Authorize]、[ChildActionOnly]、[RequireHttps]、[ValidateAntiForgeryToken]和[ValidateInput]
推荐阅读:MVC 拦截器之授权 AuthorizeAttribute
认识ASP.NET MVC的5种AuthorizationFilter
深入理解ASP.NET MVC(7)
过滤器接口类型(IActionFilter、IAuthenticationFilter、IAuthorizationFilter、IExceptionFilter和IResultFilter)
四、 小结
一、 模型扩展
1 、把请求数据转换为模型
将请求数据(比如表单数据、查询字符串数据或路由信息)转换为模型的过程称为模型绑定。模型绑定的过程分为两个阶段:
通过使用值提供器理解数据的来源
使用这些值创建/更新模型对象(通过使用模型绑定器)
(1)、使用值提供器解析请求数据
值提供器:访问能够在模型绑定过程中正确使用的信息。
(2)、创建带有模型绑定器的模型 IModelBinder
从值提供器系统中获取值,并利用获取的值创建新模型或者填充已有模型。ASP.NET MVC中默认模型绑定器可以对传统类、集合类、列表、数组甚至字典进行模型绑定。
不支持不可变对象,对象的初始值必须通过构造函数设置,之后不能改变。
示例1:Point类是不可变的,因此我们必须使用它的值构造一个新实例
using System; using System.Collections.Generic; using System.Drawing; using System.Web.Mvc; namespace WebApplication3.Areas.ModelBinder.Utility { public class PointModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { //值提供器 var valueProvider = bindingContext.ValueProvider; //从值提供器上获取值,创建新模型 int x = (int)valueProvider.GetValue("X").ConvertTo(typeof(int)); int y = (int)valueProvider.GetValue("Y").ConvertTo(typeof(int)); return new Point(x,y); } } }
当创建一个新的模型绑定器时,我们需要告知ASP.NET MVC框架存在一个新的模型绑定器以及何时使用它。
可以使用[ModelBinder]特性来装饰绑定类,也可以在ModelBinders.Binders的全局列表中注册新的模型绑定器。
using System.Drawing; using System.Web.Mvc; using WebApplication3.Areas.ModelBinder.Utility; namespace WebApplication3.Areas.ModelBinder { public class ModelBinderAreaRegistration : AreaRegistration { public override string AreaName { get { return "ModelBinder"; } } public override void RegisterArea(AreaRegistrationContext context) { context.MapRoute( "ModelBinder_default", "ModelBinder/{action}/{id}", new { controller = "ModelBinder", action = "Index", id = UrlParameter.Optional } ); //ModelBinders.Binders全局列表中注册新的模型绑定器 ModelBinders.Binders.Add(typeof(Point), new PointModelBinder()); } } }控制器、视图如下:
using System; using System.Drawing; using System.Web.Mvc; namespace WebApplication3.Areas.ModelBinder.Controllers { public class ModelBinderController : Controller { public ActionResult Index() { return View(new Point(0, 0)); } [HttpPost] public ActionResult Index(Point pt) { //在本示例中,默认情况下客户端端验证是关闭的,以便您可以更容易地进入执行服务器端验证的代码。 //你可以在禁用客户端验证的视图中注释该行。显示客户端验证也适用于此示例。 if (ModelState.IsValid) TempData["Flash"] = String.Format("Bind success! X = {0}, Y = {1}", pt.X, pt.Y); return View(pt); } } }
@model System.Drawing.Point @{ ViewBag.Title = "Model Binder Sample"; } @{ Html.EnableClientValidation(false); } @* 删除/注释此行以显示客户端验证仍然有效。 *@ @using (Html.BeginForm()) { <p>@Html.ValidationSummary(excludePropertyErrors: true)</p> <p> @Html.LabelFor(m => m.X) @Html.EditorFor(m => m.X) @Html.ValidationMessageFor(m => m.X) </p> <p> @Html.LabelFor(m => m.Y) @Html.EditorFor(m => m.Y) @Html.ValidationMessageFor(m => m.Y) </p> <p><input type="submit" /></p> }
效果:
示例2:验证绑定的值
Get<int>(controllerContext, bindingContext, "X") 由Get方法调用验证using System; using System.Collections.Generic; using System.Drawing; using System.Web.Mvc; namespace WebApplication3.Areas.ModelBinder.Utility { public class PointModelBinder : IModelBinder { //当系统开始模型绑定时,模型参数名称被设置为bindingContext.ModelName中的值(本例控制器参数时pt) public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { //如果值提供器,名称存在(如:找到pt开头),那么使用的值的名称应该是pt.X和pt.Y //如果名称不存在(如:找不到pt开头),那么名称中只有X或Y的值 if (!String.IsNullOrEmpty(bindingContext.ModelName) && !bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { if (!bindingContext.FallbackToEmptyPrefix) return null; bindingContext = new ModelBindingContext { ModelMetadata = bindingContext.ModelMetadata, ModelState = bindingContext.ModelState, PropertyFilter = bindingContext.PropertyFilter, ValueProvider = bindingContext.ValueProvider }; } //在ModelMetadata中设置一个Point对象的空实例。 //由Get方法调用验证 bindingContext.ModelMetadata.Model = new Point(); return new Point( Get<int>(controllerContext, bindingContext, "X"), Get<int>(controllerContext, bindingContext, "Y") ); } private TModel Get<TModel>(ControllerContext controllerContext, ModelBindingContext bindingContext, string name) { //获取完全限定名称 string fullName = name; if (!String.IsNullOrWhiteSpace(bindingContext.ModelName)) fullName = bindingContext.ModelName + "." + name; //从值提供程序获取值 ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(fullName); //在模型状态中记录,以便用户可以看到他们输入的值 ModelState modelState = new ModelState { Value = valueProviderResult }; bindingContext.ModelState.Add(fullName, modelState); //获得属性模型元数据的副本 ModelMetadata metadata = bindingContext.PropertyMetadata[name]; //使用模型元数据来决定是否将空字符串转换为null string attemptedValue = valueProviderResult.AttemptedValue; if (metadata.ConvertEmptyStringToNull && String.IsNullOrWhiteSpace(attemptedValue)) attemptedValue = null; TModel model; bool invalidValue = false; try { //尝试将值转换为正确的类型 model = (TModel)valueProviderResult.ConvertTo(typeof(TModel)); metadata.Model = model; } catch (Exception) { //转换失败,因此返回该类型的默认值。并将尝试的值设置为模型元数据。 model = default(TModel); metadata.Model = attemptedValue; invalidValue = true; } //运行所有验证器,并在模型状态的错误集合中记录每一个验证错误 IEnumerable<ModelValidator> validators = ModelValidatorProviders.Providers.GetValidators(metadata, controllerContext); foreach (var validator in validators) foreach (var validatorResult in validator.Validate(bindingContext.Model)) modelState.Errors.Add(validatorResult.Message); //记录数据类型转换错误,如果发生失败并且没有其他验证规则失败,就返回该值 if (invalidValue && modelState.Errors.Count == 0) modelState.Errors.Add( String.Format( "The value '{0}' is not a valid value for {1}.", attemptedValue, metadata.GetDisplayName() ) ); return model; } } }
效果:
https://www.cnblogs.com/SkySoot/p/6050251.html
Asp.net MVC的Model Binder工作流程以及扩展方法(1) - Custom Model Binder
2 、用元数据描述模型
ASP.NET MVC2中引入了模型元数据系统,用来帮助描述用于协助HTML生成和模型验证的模型元数据信息。ASP.NET MVC支持通过应用于类和属性的特性所表示的模型元数据。
这些特性主要包含在System.ComponetModel(.NET 1.0中引入)和System.ComponetModel.DataAnnotations(.NET 3.5 SP1和ASP.NET Dynamic Data一起被引入)中。
实现一个元数据提供器意味着需要继承类ModelMetadataProvider,并实现其中的3个抽象方法:
A. GetMetadataForType 返回关于整个类的元数据。
B. GetMetadataForProperty 返回类上单个属性的元数据。
C. GetMetadataForProperties 返回类上所有属性的元数据。
还有一个名为AssociatedMetadataProvider的派生类,可以被计划通过特性提供元数据的元数据提供器使用。它把上述三个方法的调用压缩到对CreateMetadata方法的调用,并传递附加到模型和模型属性的特性列表。由于简化了API和对元数据“兄弟类”的自动支持,因此如果要编写用特性装饰模型的元数据提供器,那么使用AssociatedMetadataProvider作为提供器的基类就是一个不错的选择。
https://book.2cto.com/201301/13269.html
3 、验证模型
实现验证器需要继承基类 ModelValidatorProviders,并实现返回给定模型的验证器的方法,给定模型有ModelMetadata的一个实例和ControllerContext表示。我们可以通过使用ModelValidatorProviders.Providers来注册自定义的模型验证器提供器。ModelValidatorProviders.Providers.Add
二、 视图扩展
视图是操作返回结果的最常见类型。视图通常是带有一些代码的模板,可以用来根据输入(模型)自定义输出。ASP.NET MVC默认安装了两个视图引擎:即在MVC 1.0中的WebForms视图引擎和Razor视图引擎(MVC3)。
ASP.NET MVC第三方视图引擎包括Spark、NHaml和NVelocity等。
1 、自定义视图引擎
2、 编写HTML辅助方法
3、 编写Razor辅助方法
三、 控制器扩展
通过数据访问层与模型对话,对如何实现用户要求的活动作出初步决定,并决定如何使用视图、JSON、XML等做出响应。1 、操作选择
(1)、操作名称选择
示例1:为Action重命一个新的名称//为Action定义一个新的名称 [ActionName("B")] public ActionResult A() { return View("a"); }
使用:注意不能通过地址使用 http://localhost:4405/index/B
@{Html.RenderAction("B");}
示例2:Action方法名以Product-开头
public class MyActionName : ActionNameSelectorAttribute { public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo) { return actionName.StartsWith("Product-"); } }
[MyActionName] public ActionResult A() { return View("a"); }http://localhost:4405/Home/Product-A
(2)、方法选择器
示例1:请求只能是Ajax请求public class AjaxOnly : ActionMethodSelectorAttribute { public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo) { return controllerContext.HttpContext.Request.IsAjaxRequest(); } }
[AjaxOnly] public ActionResult A() { return View("a"); }
2、 操作过滤器
(1)、身份验证过滤器
(2)、授权过滤器
需要实现IAuthorizationFilter接口,授权过滤器在身份验证过滤器之后执行。有些类实现了该接口,其中包括[Authorize]、[ChildActionOnly]、[RequireHttps]、[ValidateAntiForgeryToken]和[ValidateInput]
推荐阅读:MVC 拦截器之授权 AuthorizeAttribute
认识ASP.NET MVC的5种AuthorizationFilter
深入理解ASP.NET MVC(7)
(3)、异常过滤器
(4)、过滤器重写
推荐阅读:MVC 自定义拦截器 IActionFilter(或ActionFilterAttribute)、IExceptionFilter(或HandleErrorAttribute)过滤器接口类型(IActionFilter、IAuthenticationFilter、IAuthorizationFilter、IExceptionFilter和IResultFilter)
3 、提供自定义结果
public ActionResult Index() { var model = new Person { FirstName="Brad", LastName="Wilson", Blog="http;//www.aa.com" }; //将类序列化xml表示 return new XmlResult(model); }
public class XmlResult : ActionResult { private object data; public XmlResult(object data) { this.data = data; } public override void ExecuteResult(ControllerContext context) { var seralizer = new XmlSerializer(data.GetType()); var response = context.HttpContext.Response.OutputStream; context.HttpContext.Response.ContentType = "text/xml"; seralizer.Serialize(response,data); } }
四、 小结
相关文章推荐
- 艾伟:ASP.NET MVC,深入浅出IModelBinder,在Post方式下慎用HtmlHelper
- ASP.NET MVC,深入浅出IModelBinder,在Post方式下慎用HtmlHelper
- 详解ASP.NET MVC 常用扩展点:过滤器、模型绑定
- Asp.net MVC的Model Binder工作流程以及扩展方法(1)
- Asp.net MVC 示例项目"Suteki.Shop"分析之---ModelBinder 推荐
- ASP.NET MVC,深入浅出IModelBinder,在Post方式下慎用HtmlHelper
- Asp.net MVC的Model Binder工作流程以及扩展方法(3) - DefaultModelBinder
- ASP.NET MVC 常用扩展点:过滤器、模型绑定等
- ASP.NET MVC 常用扩展点:过滤器、模型绑定等
- ASP.NET MVC 2扩展点之Model Binder实例分析
- ASP.NET MVC 2扩展点之Model Binder
- Asp.net MVC的Model Binder工作流程以及扩展方法(2) - Binder Attribute
- Asp.net MVC的Model Binder工作流程以及扩展方法(1) - Custom Model Binder
- ASP.NET MVC 过滤器(五) 推荐
- 一起谈.NET技术,ASP.NET MVC 2扩展点之Model Binder
- 扩展ASP.NET MVC三层框架且使用StructureMap实现依赖注入1-Model层
- ASP.NET MVC 扩展之 JsonpResult ,用来提供轻量级跨域调用服务
- 玩转Asp.net MVC 的八个扩展点
- 13个 ASP.NET MVC 的扩展
- Asp.Net MVC 扩展联想控件