与ActionFilter相关的接口有2个:
□ IActionFilter 对action执行前后处理
void OnActionExecuting(ActionExecutingContext filterContext);
可以在此对请求处理,甚至开启一个新的请求。
void OnActionExecuted(ActonExecutedContext filterContext);
可以在此对返回结果处理,甚至取消返回结果。
关于参数ActionExecutingContext和ActonExecutedContext共有的:
都继承于ControllerContext。
都有ActionDescriptor属性:提供了action的细节
都有ActionResult属性:当设置为null的时候取消整个请求
关于ActonExecutedContext独有的:
Canceled属性:bool类型,ActionExecutedContext是否被其它action filter取消
Exception属性:action filter和action抛出的异常
ExceptionHandled属性:bool类型,异常是否被处理
□ IResultFilter 对action返回结果前后做处理
方法与属性与IActionFilter类似。
void OnResultExecuted(ResultExecutedContext filterContext);
void OnResultExecuting(ResultExecutingContext filterContext);
实例:继承ActionFilterAttribute为登录密码加密
ActionFilterAttribute包含了如下4个方法:
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActonExecutedContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
void OnResultExecuting(ResultExecutingContext filterContext);
所以,我们可以在派生类中重写这4个方法。
□ 思路
→在执行action之前对密码加密
→在执行action之后,根据是否登录成功,来决定返回成功或重新登录视图
→在action返回结果之后,再追加一些内容
□ 继承ActionFilterAttribute
class="alt">using System;using System.Security.Cryptography;using System.Text;using System.Web.Mvc;using System.Web.Security;namespace MvcApplication1.Extension{public class EncryptLoginAttribute : ActionFilterAttribute
{private string username;
private string password;
private bool isAuthorized = false;
private string longdate;
private string lastTry;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{username = filterContext.HttpContext.Request.Form["username"];
password = filterContext.HttpContext.Request.Form["password"];MD5 md5Hash = MD5.Create();
string md5Password = GetMD5Hash(md5Hash, password); bool result = Membership.ValidateUser(username, md5Password); if (result) { FormsAuthentication.SetAuthCookie(username, false); isAuthorized = true;longdate = DateTime.Now.ToLongDateString();
}
else { isAuthorized = false; lastTry = DateTime.Now.ToShortDateString() + "-" + DateTime.Now.ToShortTimeString();}
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{ if (isAuthorized) {filterContext.Result = new ViewResult(){ViewName = "Welcome"};
}
else { ViewResult result = new ViewResult(); result.ViewName = "Index"; result.ViewBag.message = "Login fail";filterContext.Result = result;
}
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{if (filterContext.Exception == null && !filterContext.Canceled)
{ViewResult result = (ViewResult)filterContext.Result;
if (result != null)
{if (result.ViewName == "Welcome")
{ filterContext.HttpContext.Response.Write("<p style='color:Green;'><br/>Today is "+ longdate + "<br/></p>");}
else if (result.ViewName == "Index")
{filterContext.HttpContext.Response.Write("<p style='color:Red;'><br />Last Login attemp at "+lastTry+"<br/></p>");
}
filterContext.Result = result;
}
}
}
private static string GetMD5Hash(MD5 md5Hash, string input)
{ //string→byte[] byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); StringBuilder stringBuilder = new StringBuilder();foreach (byte b in data)
{ stringBuilder.Append(b.ToString("x2"));}
return stringBuilder.ToString();}
}
}
□ HomeController
using System.Web.Mvc;using System.Web.Security;using MvcApplication1.Extension;namespace MvcApplication1.Controllers{public class HomeController : Controller
{ public ActionResult Index() { return View();}
[HttpPost]
[EncryptLogin]
public ActionResult Login(string username, string password)
{ //TODO:保存到数据库return null;
}
public ActionResult SignOut() {FormsAuthentication.SignOut();
return RedirectToAction("Index");
}
}
}
□ Home/Index.cshtml为登录页
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml";}
<h2>Index</h2>
<p style="color: red;">@ViewBag.message</p>@using (Html.BeginForm("Login", "Home", FormMethod.Post, new {id = "loginForm"}))
{<p>
用户名:@Html.TextBox("username", null, new {style = "width:100px"})
</p>
<p>
密码: @Html.Password("password", null, new {style = "width: 100px"})
</p>
<p>
<input type="submit" name="login" value="登录"/>
</p>
}
□ web.config相关配置
<authentication mode="Forms">
<forms loginUrl="~/Home/Index" timeout="2880">
<credentials passwordFormat="Clear">
<user name="name" password="21218cca77804d2ba1922c33e0151105"/>
</credentials>
</forms>
</authentication>
□ 登录成功视图:/Shared/Welcome.cshtml
@{
ViewBag.Title = "Welcome";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>登录成功~~</h2>
@Html.ActionLink("登出","SignOut","Home")
登录页:

登录失败:

□ 如果想在全局使用
filters.Add(new EncryptLoginAttribute());
□ 备注
暂没有把登录成功显示页面调试出来,因为,当使用FormsAuthentication.Authenticate(username, md5Password)时,提示此方法已经过时;而使用Membership.ValidateUser(username, md5Password)时,对应的Web.config如何配置,暂没细究。
参考资料:
MVC Filters Part 3 - Action Filter and Action Result Filter