返璞归真 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)]
public 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()]
public 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
public ActionResult OutputCacheDemo()
{
return Content(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
} public ActionResult HandleErrorDemo()
{
throw new Exception("HandleErrorDemo");
} // Authorize() - 验证。走的是 membership
[Authorize(Users = "user")]
// [Authorize(Roles = "role")]
// Request.IsAuthenticated - 返回一个 bool 值,用于指示请求是否通过了验证
public ActionResult AuthorizeDemo()
{
return Content("Authorize");
} // 自定义的 Action Filter 的 Demo
[MyFilter()]
public 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
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext.Current.Response.Write("OnActionExecuting" + "<br />");
} public override void OnActionExecuted(ActionExecutedContext filterContext)
{
HttpContext.Current.Response.Write("OnActionExecuted" + "<br />");
} public override void OnResultExecuting(ResultExecutingContext filterContext)
{
HttpContext.Current.Response.Write("OnResultExecuting" + "<br />");
} public 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
{
public 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>
public 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()]
//public static void MyClassInitialize(TestContext testContext)
//{
//}
//
//使用 ClassCleanup 在运行完类中的所有测试后再运行代码
//[ClassCleanup()]
//public static void MyClassCleanup()
//{
//}
//
//使用 TestInitialize 在运行每个测试前先运行代码
//[TestInitialize()]
//public void MyTestInitialize()
//{
//}
//
//使用 TestCleanup 在运行完每个测试后运行代码
//[TestCleanup()]
//public 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/")]
public 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);
}
}
}
OK
[源码下载]
返璞归真 asp.net mvc (5) - Action Filter, UpdateModel, ModelBinder, Ajax, Unit Test的更多相关文章
- ASP.NET MVC的Action Filter
一年前写了一篇短文ASP.NET MVC Action Filters,整理了Action Filter方面的资源,本篇文章详细的描述Action Filter.Action Filter作为一个可以 ...
- 理解ASP.NET MVC Framework Action Filters
原文:http://www.cnblogs.com/darkdawn/archive/2009/03/13/1410477.html 本指南主要解释action filters,action filt ...
- 返璞归真 asp.net mvc (3) - Controller/Action
原文:返璞归真 asp.net mvc (3) - Controller/Action [索引页] [源码下载] 返璞归真 asp.net mvc (3) - Controller/Action 作者 ...
- ASP.NET MVC 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁
在开发程序的过程中,稍微不注意就会隐含有sql注入的危险.今天我就来说下,ASP.NET mvc 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁.不用每下地方对参数的值都进行检 ...
- 返璞归真 asp.net mvc (13) - asp.net mvc 5.0 新特性
[索引页][源码下载] 返璞归真 asp.net mvc (13) - asp.net mvc 5.0 新特性 作者:webabcd 介绍asp.net mvc 之 asp.net mvc 5.0 新 ...
- 返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller
原文:返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller [索引页][源码下载] 返璞归真 asp.net mvc (7) - asp.net ...
- 返璞归真 asp.net mvc (4) - View/ViewEngine
原文:返璞归真 asp.net mvc (4) - View/ViewEngine [索引页] [源码下载] 返璞归真 asp.net mvc (4) - View/ViewEngine 作者:web ...
- 返璞归真 asp.net mvc (1) - 添加、查询、更新和删除的 Demo
原文:返璞归真 asp.net mvc (1) - 添加.查询.更新和删除的 Demo [索引页] [源码下载] 返璞归真 asp.net mvc (1) - 添加.查询.更新和删除的 Demo 作者 ...
- 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API
原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API [索引页][源码下载] 返璞归真 asp.net mvc (10) - asp.net ...
随机推荐
- Visual Studio 2008中FormatX源代码格式化插件
原地址:http://www.cr173.com/html/15492_1.html 我总是对组里的兄弟代码规范性近乎完美的要求,举个简单的例子: 1. 每个方法必须有注释,方法参数详细说明 2. ...
- 15个nosql
1.MongoDB 介绍 MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.主要解决的是海量数据的访问效率问题,为WEB应用提供可扩展的高性能数据存 储解决方案.当数据量达到50GB以 ...
- leetcode第一刷_Unique Paths
从左上到右下,仅仅能向右或向下,问一共同拥有多少种走法. 这个问题当然能够用递归和dp来做,递归的问题是非常可能会超时,dp的问题是须要额外空间. 事实上没有其它限制条件的话,这个问题有个非常easy ...
- 开玩笑Web它servlet(五岁以下儿童)---- 如何解决servlet线程安全问题
servlet默认值是安全线的存在,但说白,servlet安全线实际上是一个多线程线程安全问题.因为servlet它正好是一个多线程的安全问题出现. 每次通过浏览器http同意提交请求,将一个实例se ...
- HTML5线性图表 图表数据区域可着色
这是一款基于Canvas的HTML5图表应用,在图表数据初始化的时候伴随动画效果. 在线演示: 点击演示 源代码下载: 点击下载 核心jQuery代码: var myData = { labels ...
- 解析汽车B2C商城网站四种盈利模式
汽车已成为家庭的日常用品,汽车的配套设施也成为销售的热点,汽车B2C电子商城为行业营销的新平台,汽车B2C电子商务网站盈利的模式是怎样的?创新的盈利模式才能在行业竞争中生存. 资讯产品一体模式 网站的 ...
- cocos2d-x 消类游戏,类似Diamond dash 设计
前几天刚刚在学习cocos2d-x,无聊之下自己做了一个类似Diamond dash的消类游戏,今天放到网上来和大家分享一下.我相信Diamond dash这个游戏大家都玩过,游戏的规则是这样的,有一 ...
- JAVA逆向&反混淆-追查Burpsuite的破解原理(转)
0x00 摘要: 本系列文章通过对BurpLoader的几个版本的逆向分析,分析Burpsuite的破解原理,分析Burpsuite认证体系存在的安全漏洞. 0x01 JD-GUI的用途与缺陷: JD ...
- centos6搭建本地openstack软件源
1.把相关软件包所有下载到本地机器 wget -np -nH –cut-dirs=1 -r -c -L –exclude-directories=repodata –accept=rpm,gz,xml ...
- html+css实现登录界面
<!DOCTYPE html> <style type="text/css"> body{ background-color: #555555; } #ti ...