返璞归真 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 

        // HandleError - 出现异常时跳转到  Error.aspx(先在指定的 view 文件夹找,找不到再在 Shared 文件夹下找) 
        // 需要 web.config 配置 - <customErrors mode= "On" /> 
        [HandleError] 
         public  class FilterDemoController : Controller 
        { 
                // 每一个 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)] 
ActionResult Details() ActionResult Details(int id) 
                { 
                        var product = ps.GetProduct(id); 

                        return View( "Details", product); 
                } 

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

ActionResult HandleErrorDemo() ActionResult HandleErrorDemo() 
                { 
                        throw  new Exception( "HandleErrorDemo"); 
                } 

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

                // 自定义的 Action Filter 的 Demo 
                [MyFilter()] 
ActionResult MyFilterDemo() ActionResult MyFilterDemo() 
                { 
                        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 

        /**//// <summary> 
        /// 自定义的 Action Filter,需要继承 ActionFilterAttribute 
        /// </summary> 
         public  class MyFilter : ActionFilterAttribute 
        { 
override void OnActionExecuting() override void OnActionExecuting(ActionExecutingContext filterContext) 
                { 
                        HttpContext.Current.Response.Write( "OnActionExecuting" +  "<br />"); 
                } 

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

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

override void OnResultExecuted() override void OnResultExecuted(ResultExecutedContext filterContext) 
                { 
                        HttpContext.Current.Response.Write( "OnResultExecuted" +  "<br />"); 
                } 
        } 
}
 
Details.aspx
<%@ 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"
        <% 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> 
        <% 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 

         public  class UpdateModelController : Controller 
        { 
ActionResult Details() ActionResult Details( string name, int age) 
                { 
                        User user =  new User(); 

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

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

                        ViewData.Model = user; 

                        return View(); 
                } 
        } 
}
 
Details.aspx
<%@ 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 

         public  class ModelBinderController : Controller 
        { 
                /**//// <summary> 
                /// 路由过来的或者参数过来的,会自动地赋值到对象的对应的属性上 
                /// 做这个工作的就是实现了 IModelBinder 接口的 DefaultModelBinder 
                /// </summary> 
ActionResult Details() ActionResult Details(User user) 
                { 
                        base.ViewData.Model = user; 

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

                        return View(); 
                } 
        } 
}
 
Details.aspx
<%@ 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> 
        <% 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 

        /**//// <summary> 
        ///这是 ProductControllerTest 的测试类,旨在 
        ///包含所有 ProductControllerTest 单元测试 
        ///</summary> 
        [TestClass()] 
         public  class ProductControllerTest 
        { 
                 private TestContext testContextInstance; 

                /**//// <summary> 
                ///获取或设置测试上下文,上下文提供 
                ///有关当前测试运行及其功能的信息。 
                ///</summary> 
                 public TestContext TestContext 
                { 
                         get 
                        { 
                                return testContextInstance; 
                        } 
                         set 
                        { 
                                testContextInstance = value; 
                        } 
                } 

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


                /**//// <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/")] 
void IndexTest() void IndexTest() 
                { 
                        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); 
                } 
        } 
}
 
 




     本文转自webabcd 51CTO博客,原文链接:http://blog.51cto.com/webabcd/341971 ,如需转载请自行联系原作者
相关文章
|
4月前
|
开发框架 前端开发 JavaScript
ASP.NET AJAX使用方法概述(三)
ASP.NET AJAX使用方法概述(三)
37 1
|
7天前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
20 7
|
5天前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
16 0
|
29天前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
29 0
|
30天前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?
|
1月前
|
开发框架 .NET
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
Asp.Net Core 使用X.PagedList.Mvc.Core分页 & 搜索
79 0
|
4月前
|
开发框架 缓存 前端开发
安装ASP.NET AJAX (一安装)
安装ASP.NET AJAX (一安装)
56 0
|
4月前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
63 0
|
4月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
145 0
|
4月前
|
开发框架 前端开发 .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,然后在重定向到另
253 5