第九节:从源码的角度分析MVC中的一些特性及其用法

摘要:
乍一看,这个标题有点耸人听闻。最近,我一直在思考如何写一个好的博客,让人们能够阅读它。这很容易理解和理解。以下章节重点介绍框架本身提供的特性,包括MVC组件和其他组件;在本章中,我们将重点介绍几种MVC框架提供的功能,这些框架用于方法,并模仿它们的源代码定制功能。事实上,我在DotNet的上一个高级章节中写了一篇关于功能的文章。以下是核心功能的概述。  1

一. 前世今生

  乍眼一看,该标题写的有点煽情,最近也是在不断反思,怎么能把博客写好,让人能读下去,通俗易懂,深入浅出。

  接下来几个章节都是围绕框架本身提供特性展开,有MVC程序集提供的,也有其它程序集提供;在本章节将重点介绍几个MVC框架提供的且作用于方法上的特性,并且模仿其源码自定义特性。

  其实早在前面的 DotNet进阶章节,就写过一篇关于特性的文章了,这里重新总结一下特性核心要点。

     1. 什么是特性?

   特性是一个类,在不影响程序封装的情况下,额外的给程序添加一些信息,用于运行时描述程序或者影响程序的行为。

  2. 特性的作用范围?

   提到特性的作用范围,就不得不提到 AttributeUsage了,该类本身就是一个特性,继承了Attribute类,用于约束自定义特性(你可以看到系统提供的很多特性中,均能看到它的身影),下面先看一        下它的源码:

    第九节:从源码的角度分析MVC中的一些特性及其用法第1张第九节:从源码的角度分析MVC中的一些特性及其用法第2张

   该特性有一个参数,两个核心属性,AttributeTargets参数约束了该给特性可以作用的范围,通过右面的代码可知,可以作用于:类、方法、参数、属性、返回值等等,该参数默认为ALL。

    AllowMultiple:约束该特性能否同时作用于某个元素(类、方法、属性等等)多次,默认为false。

         Inherited:约束该特性作用于基类(或其它)上,其子类能否继承该特性,默认为true。

  3. 如何自定义特性?

     简单来说,声明一个以Attribute结尾的类,继承Attribute类,然后加上AttributeTargets特性约束,一个简单的特性就产生了。

二. MVC中的常用特性

   有了前面的铺垫,这里讲解【System.Web.Mvc】程序集下的一些特性就很好理解,理解源码的同时,主要掌握其如何使用。

    MVC中提供的常用特性有:【HttpGet】、【HttpPost】、【AcceptVerbs】、【ActionName】、【NoAction】、【AllowAnonymous】、【ValidateAntiForgeryToken】、【ChildActionOnly】、【Bind】这九个特性。

  查看源码可知,其中【HttpGet】【HttpPost】【AcceptVerbs】【ActionName】【NoAction】【ChildActionOnly】均继承ActionNameSelectorAttribute类,实现了IsValidForRequest这个抽象方法,且特性约束为: [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)],显然这些特性均是作用于方法上的,且不需要同时作用,允许子类继承该特性。

   以【HttpGet】的源码为例:

 第九节:从源码的角度分析MVC中的一些特性及其用法第3张

   其中【AllowAnonymous】直接继承Attribute类,源码如下:

  第九节:从源码的角度分析MVC中的一些特性及其用法第4张

  其中【ValidateAntiForgeryToken】继承了FilterAttribute类,实现了IAuthorizationFilter接口,源码如下:

  (扩展一下:AuthorizeAttribute类也是继承了FilterAttribute类,实现了IAuthorizationFilter接口)

第九节:从源码的角度分析MVC中的一些特性及其用法第5张

1. HttpGet和HttpPost

(1).  HttpGet:只允许Get请求访问

 底层运用的AcceptVerb特性实现的,所以等价于[AcceptVerbs(HttpVerbs.Get)]或[AcceptVerbs("Get")]

 测试:前端用Ajax请求,如果非Get请求方式进行请求,则提示404找不到

(2).  HttpPost:只允许Post请求访问

 底层运用的AcceptVerb特性实现的,所以等价于[AcceptVerbs(HttpVerbs.Post)]或[AcceptVerbs("Post")]

 测试:前端用Ajax请求,如果非Post请求方式进行请求,则提示404找不到

 特别注意:如果一个方法要同时允许Get和Post请求[HttpGet]和[HttpPost]同时加载上面是错误的!!这个时候就需要使用AcceptVerb特性了(当然方法上如果什么特性也不加,什么请求均支持)

2. AcceptVerbs

AccetpVerbs:用于限定请求方式(包括:Get、Post、Put、Delete、Head、Patch、Options)

查看源码可知:该特性有两个构造函数,所有两种写法,如:只允许Get请求,可以:[AcceptVerbs(HttpVerbs.Get)]和[AcceptVerbs("Post")]

若要同时支持多种请求,可以:[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]或[AcceptVerbs("Get", "Post")]

相关测试代码如下:

第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第7张
 1        //1. 下面三种写法均为只允许Get请求
 2         //[HttpGet]
 3         //[AcceptVerbs(HttpVerbs.Get)]
 4         //[AcceptVerbs("Get")]
 5 
 6         //2. 下面三种写法均为只允许Get请求
 7         //[HttpPost]
 8         //[AcceptVerbs(HttpVerbs.Post)]
 9         //[AcceptVerbs("Post")]
10 
11         //3. 下面两种写法表示:既允许Get请求也允许Post请求
12         [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
13         //[AcceptVerbs("Get", "Post")]
14         public ActionResult TestMethordWay()
15         {
16             return Content("请求成功");
17         }
View Code
第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第9张
 1         //1. 测试只允许Get或Post请求
 2             $("#btn1").click(function () {
 3                 $.ajax({
 4                     type: "Put",   //Post 、Put
 5                     url: "TestMethordWay",
 6                     data: "",
 7                     success: function (msg) {
 8                         alert(msg);
 9                     }
10                 });
11             });
View Code

3. ActionName

 ActionName:修改Action本身的方法名

测试:请求TestActionName1方法,报404找不到

           请求TestActionName2方法,正常访问

相关测试代码如下:

第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第11张
1         /// <summary>
2         /// 名字变为:TestActionName2了
3         /// </summary>
4         /// <returns></returns>
5         [ActionName("TestActionName2")]
6         public ActionResult TestActionName1()
7         {
8             return Content("我是TestActionName1");
9         }
View Code
第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第13张
 1    //2. 测试ActionName特性
 2             $("#btn2").click(function () {
 3                 $.ajax({
 4                     type: "Get",   
 5                     url: "TestActionName2", //TestActionName1
 6                     data: "",
 7                     success: function (msg) {
 8                         alert(msg);
 9                     }
10                 });
11             });
View Code

4. NoAction

NoAction: 标记控制器中的action将不在是一个方法,不能前端Http请求访问

测试:前端页面ajax进行请求,报404找不到

     但在其它action中进行调用,能正常调用

相关测试代码如下:

第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第15张
1        /// <summary>
2         /// 标记该方法将不是一个方法
3         /// </summary>
4         /// <returns></returns>
5         [NonAction]
6         public ActionResult TestNoAction()
7         {
8             return Content("请求成功");
9         }
View Code
第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第17张
 1   //3. 测试NoAction特性
 2             $("#btn3").click(function () {
 3                 $.ajax({
 4                     type: "Get",
 5                     url: "TestNoAction",   //TestNoAction
 6                     data: "",
 7                     success: function (msg) {
 8                         alert(msg);
 9                     }
10                 });
11             });
View Code

5. AllowAnonymous

AllowAnonymous:该特性用于标记在授权期间要跳过 AuthorizeAttribute 过滤器的验证

解释:AuthorizeAttribute是MVC框架自带的实现IAuthorizationFilter过滤器的一个类,内部有一套自身业务验证(感兴趣的可以自己研究源码)

           而AllowAnonymous就是为了标记跨过AuthorizeAttribute验证的

这里不做详细测试

6. ValidateAntiForgeryToken

 ValidateAntiForgeryToken:阻止跨站请求伪造攻击(CSRF).

①. CSRF原理是什么:

  a.用户mr访问正规网站A,登录验证通过,并在用户mr处产生Cookie

  b.用户mr在不关闭A网站的情况下打开危险的B网站,在B网站中要求访问A网站,发出一个Request请求

  c.这时候浏览器带着A网站在mr出产生的Cookie进行访问A网站

  d.这时候A网站就无法判断这个cookie是谁产生的,默认就给通过了

详细见:https://www.cnblogs.com/hechunming/p/4647646.html

②:解决方案

  a. 在Controller中的action上加上特性[ValidateAntiForgeryToken]

  b. 对于增删改查操作前端调用: $.ajaxAntiForgery方法进行ajax请求(需要引入jqueryToken的js文件)

这里不做详细测试

7. ChildActionOnly

ChildActionOnly:限制操作方法只能由子操作进行调用。

  ①. 测试直接输入:http://localhost:7559/SpecialAttribute/Index2, 无法访问报错.

  ②. 需要通过RenderAction来调用(存在问题,与Unity改造框架冲突冲突)

这里RenderAction不做详细测试

8. Bind

①. 源码的角度分析:该特性可以作用于类或参数(本章节测试作用于参数)

②. 该特性有三个核心属性:

  a. Exclude:获取或设置不允许绑定的属性名称的列表(各属性名称之间用逗号分隔)

  b. Include:获取或设置允许绑定的属性名称的列表(各属性名称之间用逗号分隔),与Exclude一个道理,通常根据情况使用一个即可

  c. Prefix:获取或设置在呈现表示绑定到操作参数或模型属性的标记时要使用的前缀

不适用与ajax提交,适用于razor语法中的@{Html.TextBox(stu.id)},在现在前后端分离盛行的情况下,有点不适合了

测试:

  前端过个ajax传过来三个参数:id、name、sex, 参数中的stu只能收到id和name,sex为null,若想收到sex,需要在方法中通过request进行接收

第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第19张
 1         /// <summary>
 2         /// stu中的sex属性为null
 3         /// var 中sex为男
 4         /// </summary>
 5         /// <param name="stu"></param>
 6         /// <returns></returns>
 7         public ActionResult TestBindAttribute([Bind(Include = "id,name")]Student stu)
 8         {
 9             var sex = Request["sex"]; 
10             return Content("请求成功");
11         }
12   
View Code
第九节:从源码的角度分析MVC中的一些特性及其用法第6张第九节:从源码的角度分析MVC中的一些特性及其用法第21张
 1          //4.测试BindAttribute特性
 2             $("#btn4").click(function () {
 3                 $.ajax({
 4                     type: "Get",
 5                     url: "TestBindAttribute",   
 6                     data: {"id":"123","name":"ypf","sex":"男"},
 7                     success: function (msg) {
 8                         alert(msg);
 9                     }
10                 });
11             });    
View Code

三. 自定义一个类似的特性

要求:支持Get请求,且必须是Ajax请求

思路:由HttpGet特性可以知道:需要继承ActionMethodSelectorAttribute类,然后覆写IsValidForRequest方法即可

 1     public class HttpGetAndAjaxAttribute : ActionMethodSelectorAttribute
 2         {
 3             public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
 4             {
 5                 //1.获取请求方式
 6                 string HttpWay = controllerContext.HttpContext.Request.GetHttpMethodOverride();
 7 
 8                 //2. 获取是否是Ajax请求
 9                 bool isAjax = controllerContext.HttpContext.Request.IsAjaxRequest();
10 
11                 if (HttpWay.ToLower() == "get" && isAjax == true)
12                 {
13                     return true;
14                 }
15                 return false;
16 
17             }
18         }
19 
20         [HttpGetAndAjax]
21         public ActionResult GetAndAjax()
22         {
23             return Content("请求成功");
24         }
 1         //5.测试自定义特性
 2             $("#btn5").click(function () {
 3                 $.ajax({
 4                     type: "Get",
 5                     url: "GetAndAjax",
 6                     data: "",
 7                     success: function (msg) {
 8                         alert(msg);
 9                     }
10                 });
11             });        

第九节:从源码的角度分析MVC中的一些特性及其用法第22张

免责声明:文章转载自《第九节:从源码的角度分析MVC中的一些特性及其用法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SQLserver 表字段修改语句windbg笔记下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

文件上传的几种方式_django

一、form组件形式上传文件 缺点:页面会刷新 后台: 前端:   二、ajax形式上传 能够实现页面不刷新上传 1、原生ajax上传,使用XMLHttpRequest对象来进行上传   流程:     生成XMLHttpRequest对象     对象编写数据open()     开始发送send()     编写对象的回调函数xhr.onreadys...

ajax页面刷新小错误(提交按钮type必须为button,而不能是submit)

背景:   使用ajax提交form表单时,提交按钮的type值写为了submit,导致ajax中回调函数中的提示信息toastr.success('提交数据成功');没有执行,只执行了alert语句 ,就算toastr提示语句在alert前面写着也不执行。    function add_smoke() { $.ajax({...

JQ之$.ajax()方法以及ajax跨域请求

AJAX(Asynchronous javascript AND xml :异步javascript和xml):是一种创建交互式网页应用的网页开发技术。AJAX可以在不重新加载整个页面的情况下与服务器进行交互。 AJAX的应用范围:   登录失败不跳转页面   注册时验证用户是否存在   图片服务器进行延时加载   多页数据进行翻页   自动制新页面等。...

web前端图片上传(2)

今天发现了一种ajax上传图片的方式,是以前没有用过的,首先来说下为什么要用这种方式。是因为原来后台是用的form表单的方式来提交表单数据的。但是觉得呢,这种方式不太好,因为要刷新页面,前台只用控制台看不到传输的参数(如果哪位大神知道怎么看到,请不吝赐教),所以我们就改成了ajax的方式,结果后台老哥说,前端改改就行了,后端不用改。然后我去找到了这种aja...

Ratatype

Ratatype 是一个在线的打字教程网站,帮助人们提高键盘输入速度。开始掌握你的技能,挑战你的朋友或得到一个打字的证书。如果打字慢会浪费你宝贵的时间。如果你的打字速度提高30%,您可以每天节省20分钟的,20年就可以节省一年!这就是为什么你需要Ratatype,它是无比轻松的,完全免费的。 立即去学习 您可能感兴趣的相关文章 网站开发中很有用的 jQ...

JavaScript和Ajax部分(4)

31、 什么是jQuery选择器 1)jQuery选择器继承了CSS与Path语言的部分语法,允许通过标签名、属性名或内容对DOM元素进行快速、准确的选择,而不必担心浏览器的兼容性,通过jQuery选择器对页面的元素的精准定位,才能完成元素属性和行为的处理。  选择器是jQuery的根基,在jQuery中,对象的事件处理,遍历DOM和Ajax操作都依赖于...