前一篇中我们已经了解了Action Filter 与 内置的Filter实现,现在我们就来写一个实例。就写一个防盗链的Filter吧。
首先继承自FilterAttribute类同时实现IActionFilter接口,代码如下:
/
// <summary> /// 防盗链Filter. /// </summary>
public class
AntiOutSiteLinkAttribute : ActionFilterAttribute, IActionFilter
{ public AntiOutSiteLinkAttribute(FileType fileType) { this .FileType = fileType; } /// <summary> /// 请求的文件类型.(文件或图片) /// </summary> public FileType FileType { get ; set ; } IActionFilter 成员 #region IActionFilter 成员 void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) { HttpContextBase httpContext = filterContext.HttpContext; if ( null != httpContext.Request.UrlReferrer) { string serverDomain = httpContext.Request.Url.Host; string refDomain = httpContext.Request.UrlReferrer.Host; if (GetRootDomain(refDomain).Equals(GetRootDomain(serverDomain), StringComparison.OrdinalIgnoreCase)) { return ; // 如果根域名相同就返回 } } ContentResult cr = new ContentResult(); if (FileType == FileType.Image) { cr.ContentType = " image/jpeg " ; FileInfo fi = new FileInfo(httpContext.Server.MapPath( " ~/Content/images/outsitelink.jpg " )); if (fi.Exists) { httpContext.Response.WriteFile(fi.FullName); } else { Bitmap bmp = new Bitmap( 200 , 50 ); Graphics g = Graphics.FromImage(bmp); g.FillRectangle(Brushes.White, 0 , 0 , 200 , 50 ); g.DrawString( " 请不要盗链 " , new Font( " Arial " , 15 ), Brushes.Red, new PointF( 0 , 0 )); bmp.Save(httpContext.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif); } } else { cr.ContentType = " text/html " ; cr.Content = string .Format( " 请不要盗链。返回<a href='{0}'>{1}</a> " , Utils.AbsoluteWebRoot, BlogSettings.Instance.Name); } // 将当前的上下文的ActionResult设置为我们的cr(ContentResult) filterContext.Result = cr; } #endregion /**/ /// <summary> /// 获取网站的根域名 /// </summary> /// <param name="domain"> 网站的域名,不带"Http://" </param> /// <returns></returns> private string GetRootDomain( string domain) { if ( string .IsNullOrEmpty(domain)) { throw new ArgumentNullException( " 参数'domain'不能为空 " ); } string [] arr = domain.Split( new [] { ' . ' } , StringSplitOptions.RemoveEmptyEntries); if (arr.Length <= 2 ) { return domain; } else { return arr[arr.Length - 2 ] + " . " + arr[arr.Length - 1 ]; } } }
public enum
FileType
{ File = 1 , Image }
然后我们建立一个用于处理文件请求的Controller,并应用上我们刚才建立的Filter:
public class
FilesController : BaseController { [AntiOutSiteLink(FileType.Image)] public ActionResult Image( string
file) { return Content( " Image From 4mvc "
); } [AntiOutSiteLink(FileType.File)] public ActionResult File( string
file) { return Content( " File From 4mvc "
); } }
简单测试一下:
对于ActionFilter的应用是很广泛的,这需要你的灵活运用。对于其他应用,你可以参考我之前翻译的ASP.NET MVC Action Filter - 缓存与压缩 这一篇文章。