返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test

简介: 原文:返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test[索引页][源码下载]返璞归真 asp.
原文: 返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test

[索引页]
[源码下载]


返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test


作者: webabcd


介绍
asp.net mvc 之 Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test
  • Action Filter - 在 Controller 层对信息做过滤。如何实现自定义的 Action Filter
  • UpdateModel -  根据参数自动为对象的属性赋值
  • ModelBinder - 定义如何绑定 Model,DefaultModelBinder 实现了 IModelBinder ,其可以根据名称自动将参数赋值到对象对应的属性上
  • Ajax -  在 asp.net mvc 中使用 ajax
  • Unit Test -  在 asp.net mvc 中使用单元测试


示例
1、asp.net mvc 自带的 Action Filter 的演示
FilterDemoController.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;
using  System.Web.Mvc.Ajax;

using  MVC.Models;

namespace  MVC.Controllers
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif
{
    
// HandleError - 出现异常时跳转到 Error.aspx(先在指定的 view 文件夹找,找不到再在 Shared 文件夹下找)
    
// 需要 web.config 配置 - <customErrors mode="On" />
    [HandleError]
    
public class FilterDemoController : Controller
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
{
        
// 每一个 Filter 都有一个 Order 属性,其用来指定 Filter 的执行顺序

        
// [NonAction] - 当前方法为普通方法,不解析为 Action

        
// [AcceptVerbs(HttpVerbs)] - 调用该 Action 的 http 方法
        
// HttpVerbs 枚举成员如下: HttpVerbs.Get, HttpVerbs.Post, HttpVerbs.Put, HttpVerbs.Delete, HttpVerbs.Head


        ProductSystem ps 
= new ProductSystem();


        
// ActionName() - Action 的名称。默认值同方法名称
        [ActionName("Product")]

        
// ValidateInput() - 相当于 @ Page 的 ValidateRequest, 用于验证请求中是否存在危险代码。可防止 XSS 攻击。默认值为 true
        [ValidateInput(false)]
        
public ActionResult Details(int id)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            var product 
= ps.GetProduct(id);

            
return View("Details", product);
        }


        
// ValidateAntiForgeryToken() - 避免 CSRF 攻击(需要视图页面中使用 Html.AntiForgeryToken())。原理:生成一个随机字符串,将其同时写入 cookie 和 hidden,当 form 提交到 action 时,验证二者是否相等并且验证提交源是否是本站页面(详查 asp.net mvc 的源代码)
        
// 拼 sql 的时候防止 sql 注入:使用 @Parameter 的方式
        [ValidateAntiForgeryToken()]
        
public ActionResult ValidateAntiForgeryTokenTest()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
return Content("ValidateAntiForgeryToken");
        }


        
// OutputCache() - 缓存。Duration - 缓存秒数。VaryByParam - none, *, 多个参数用逗号隔开
        [OutputCache(Duration = 10, VaryByParam = "none")]
        
// [OutputCache(CacheProfile = "MyCache")] - 通过配置文件对缓存做设置。可以参看 http://www.cnblogs.com/webabcd/archive/2007/02/15/651419.html
        public ActionResult OutputCacheDemo()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
return Content(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
        }


        
public ActionResult HandleErrorDemo()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
throw new Exception("HandleErrorDemo");
        }


        
// Authorize() - 验证。走的是 membership
        [Authorize(Users = "user")]
        
// [Authorize(Roles = "role")]
        
// Request.IsAuthenticated - 返回一个 bool 值,用于指示请求是否通过了验证
        public ActionResult AuthorizeDemo()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
return Content("Authorize");
        }


        
// 自定义的 Action Filter 的 Demo
        [MyFilter()]
        
public ActionResult MyFilterDemo()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
return Content("MyFilterDemo" + "<br />");
        }

    }

}


自定的 Action Filter 的实现
MyFilter.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;

using  System.Web.Mvc;

namespace  MVC
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif
{
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
/**//// <summary>
    
/// 自定义的 Action Filter,需要继承 ActionFilterAttribute
    
/// </summary>

    public class MyFilter : ActionFilterAttribute
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
{
        
public override void OnActionExecuting(ActionExecutingContext filterContext)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            HttpContext.Current.Response.Write(
"OnActionExecuting" + "<br />");
        }


        
public override void OnActionExecuted(ActionExecutedContext filterContext)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            HttpContext.Current.Response.Write(
"OnActionExecuted" + "<br />");
        }


        
public override void OnResultExecuting(ResultExecutingContext filterContext)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            HttpContext.Current.Response.Write(
"OnResultExecuting" + "<br />");
        }


        
public override void OnResultExecuted(ResultExecutedContext filterContext)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            HttpContext.Current.Response.Write(
"OnResultExecuted" + "<br />");
        }

    }

}


Details.aspx
img_405b18b4b6584ae338e0f6ecaf736533.gif img_1c53668bcee393edac0d7b3b3daff1ae.gif <% @ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC.Models.Products>"  %>

< asp:Content  ID ="Content1"  ContentPlaceHolderID ="TitleContent"  runat ="server" >
    Details
</ asp:Content >
< asp:Content  ID ="Content2"  ContentPlaceHolderID ="MainContent"  runat ="server" >
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif    
<%  Html.BeginForm("ValidateAntiForgeryTokenTest""FilterDemo");  %>
    
<% =  Html.AntiForgeryToken()  %>
    
< h2 >
        Details
</ h2 >
    
< p >
        
< strong > ProductID: </ strong >
        
<% =  Html.Encode(Model.ProductID)  %>
    
</ p >
    
< p >
        
< strong > ProductName: </ strong >
        
<% =  Html.Encode(Model.ProductName)  %>
    
</ p >
    
< p >
        
< input  type ="submit"  name ="btnSubmit"  value ="submit"   />
    
</ p >
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif    
<%  Html.EndForm();  %>
</ asp:Content >


2、应用 UpdateModel 的 Demo
UpdateModelController.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;
using  System.Web.Mvc.Ajax;

namespace  MVC.Controllers
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif
{
    
public class UpdateModelController : Controller
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
{
        
public ActionResult Details(string name, int age)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            User user 
= new User();

            
// UpdateModel() 和 TryUpdateModel() - 系统根据参数自动为对象的属性赋值

            
base.UpdateModel(user); // 失败抛异常
            
// base.TryUpdateModel(user); // 失败不抛异常

            ViewData.Model 
= user;

            
return View();
        }

    }

}


Details.aspx
img_405b18b4b6584ae338e0f6ecaf736533.gif img_1c53668bcee393edac0d7b3b3daff1ae.gif <% @ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC.Controllers.User>"  %>

< asp:Content  ID ="Content1"  ContentPlaceHolderID ="TitleContent"  runat ="server" >
    Details
</ asp:Content >
< asp:Content  ID ="Content2"  ContentPlaceHolderID ="MainContent"  runat ="server" >
    
< h2 >
        Details
</ h2 >
    
< p >
        
< strong > UserId: </ strong >
        
<% =  Model.ID  %>
    
</ p >
    
< p >
        
< strong > Name: </ strong >
        
<% =  Model.Name %>
    
</ p >
    
< p >
        
< strong > Age: </ strong >
        
<% =  Model.Age %>
    
</ p >
</ asp:Content >


3、演示什么是 ModelBinder
ModelBinderController.cs
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Web.Mvc;
using  System.Web.Mvc.Ajax;

namespace  MVC.Controllers
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif
{
    
public class ModelBinderController : Controller
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
{
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
/**//// <summary>
        
/// 路由过来的或者参数过来的,会自动地赋值到对象的对应的属性上
        
/// 做这个工作的就是实现了 IModelBinder 接口的 DefaultModelBinder
        
/// </summary>

        public ActionResult Details(User user)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
base.ViewData.Model = user;

            
// ModelState - 保存 Model 的状态,包括相应的错误信息等
            if (!base.ModelState.IsValid)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
foreach (var state in ModelState)
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif                
{
                    
if (!base.ModelState.IsValidField(state.Key))
                        ViewData[
"errorMsg"= state.Key + "/" + state.Value.Value.AttemptedValue + "<br />";
                }

            }


            
return View();
        }

    }

}


Details.aspx
img_405b18b4b6584ae338e0f6ecaf736533.gif img_1c53668bcee393edac0d7b3b3daff1ae.gif <% @ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage"  %>

< asp:Content  ID ="Content1"  ContentPlaceHolderID ="TitleContent"  runat ="server" >
    Details
</ asp:Content >
< asp:Content  ID ="Content2"  ContentPlaceHolderID ="MainContent"  runat ="server" >
    
< h2 >
        Details
</ h2 >
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif    
<%  var model = ((MVC.Controllers.User)ViewData.Model);  %>
    
< p >
        
< strong > UserId: </ strong >
        
<% =  model.ID  %>
    
</ p >
    
< p >
        
< strong > Name: </ strong >
        
<% =  model.Name  %>
    
</ p >
    
< p >
        
< strong > Age: </ strong >
        
<% =  model.Age  %>
    
</ p >
    
< p >
        
< strong > error: </ strong >
        
<% =  ViewData[ " errorMsg " %>
    
</ p >
</ asp:Content >


4、使用 ajax 的 Demo
     < p >
        Ajax
        
        
< script  src ="http://www.cnblogs.com/Scripts/MicrosoftAjax.debug.js"  type ="text/javascript" ></ script >
        
< script  src ="http://www.cnblogs.com/Scripts/MicrosoftMvcAjax.debug.js"  type ="text/javascript" ></ script >
                       
        
< br  />
        
        
<!--  AjaxHelper 简要说明  -->
        
<% =  Ajax.ActionLink(
                
" ProductId 为 1 的详情页 " ,
                
" Details " ,
                
" Product " ,
                
new  { id  =   1  },
                
new  AjaxOptions { UpdateTargetId  =   " ajax "  }
            )
        
%>  
    
</ p >
    
< div  id ="ajax"   />


5、在 VS 中做单元测试
ProductControllerTest.cs
using  MVC.Controllers;
using  Microsoft.VisualStudio.TestTools.UnitTesting;
using  Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using  System.Web.Mvc;

using  MVC.Models;
using  System.Collections.Generic;

namespace  MVC.Tests
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif
{
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
/**//// <summary>
    
///这是 ProductControllerTest 的测试类,旨在
    
///包含所有 ProductControllerTest 单元测试
    
///</summary>

    [TestClass()]
    
public class ProductControllerTest
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif    
{
        
private TestContext testContextInstance;

img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
/**//// <summary>
        
///获取或设置测试上下文,上下文提供
        
///有关当前测试运行及其功能的信息。
        
///</summary>

        public TestContext TestContext
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            
get
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                
return testContextInstance;
            }

            
set
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif            
{
                testContextInstance 
= value;
            }

        }


img_7a2b9a960ee9a98bfd25d306d55009f8.gifimg_2887d91d0594ef8793c1db92b8a1d545.gif        
附加测试属性#region 附加测试属性
        
// 
        
//编写测试时,还可使用以下属性:
        
//
        
//使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        
//[ClassInitialize()]
        
//public static void MyClassInitialize(TestContext testContext)
        
//{
        
//}
        
//
        
//使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        
//[ClassCleanup()]
        
//public static void MyClassCleanup()
        
//{
        
//}
        
//
        
//使用 TestInitialize 在运行每个测试前先运行代码
        
//[TestInitialize()]
        
//public void MyTestInitialize()
        
//{
        
//}
        
//
        
//使用 TestCleanup 在运行完每个测试后运行代码
        
//[TestCleanup()]
        
//public void MyTestCleanup()
        
//{
        
//}
        
//
        #endregion



img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
/**//// <summary>
        
///Index 的测试
        
///</summary>

        // TODO: 确保 UrlToTest 属性指定一个指向 ASP.NET 页的 URL(例如,
        
// http:///Default.aspx)。这对于在 Web 服务器上执行单元测试是必需的,
        
//无论要测试页、Web 服务还是 WCF 服务都是如此。
        [TestMethod()]
        [HostType(
"ASP.NET")]
        [AspNetDevelopmentServerHost(
"C:\\MVC\\MVC""/")]
        [UrlToTest(
"http://localhost:2005/")]
        
public void IndexTest()
img_2887d91d0594ef8793c1db92b8a1d545.gifimg_7a2b9a960ee9a98bfd25d306d55009f8.gif        
{
            ProductController target 
= new ProductController(); // TODO: 初始化为适当的值
            int pageIndex = 0// TODO: 初始化为适当的值

            ViewResult actual;
            actual 
= target.Index(pageIndex) as ViewResult;

            Assert.AreNotEqual(actual.ViewData.Model 
as List<Products>null);
        }

    }

}



OK
[源码下载]
目录
相关文章
|
1月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
29 0
|
1月前
mvc.net分页查询案例——mvc-paper.css
mvc.net分页查询案例——mvc-paper.css
5 0
|
1月前
|
XML 开发框架 .NET
C# .NET面试系列八:ADO.NET、XML、HTTP、AJAX、WebService
## 第二部分:ADO.NET、XML、HTTP、AJAX、WebService #### 1. .NET 和 C# 有什么区别? .NET(通用语言运行时): ```c# 定义:.NET 是一个软件开发框架,提供了一个通用的运行时环境,用于在不同的编程语言中执行代码。 作用:它为多语言支持提供了一个统一的平台,允许不同的语言共享类库和其他资源。.NET 包括 Common Language Runtime (CLR)、基础类库(BCL)和其他工具。 ``` C#(C Sharp): ```c# 定义: C# 是一种由微软设计的面向对象的编程语言,专门为.NET 平台开发而创建。 作
174 2
|
1月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
97 5
|
前端开发 数据安全/隐私保护
net MVC中的模型绑定、验证以及ModelState
net MVC中的模型绑定、验证以及ModelState 模型绑定 模型绑定应该很容易理解,就是传递过来的数据,创建对应的model并把数据赋予model的属性,这样model的字段就有值了。
1653 0
|
3月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
41 0
|
3月前
|
XML 前端开发 定位技术
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
25 0
|
3月前
|
前端开发
.net core mvc获取IP地址和IP所在地(其实是百度的)
.net core mvc获取IP地址和IP所在地(其实是百度的)
123 0
|
8月前
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
116 0
|
9月前
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(一)
[回馈]ASP.NET Core MVC开发实战之商城系统(一)
113 0