AOP基础:参考文章
文章基于MVC框架。
1.MVC路由小知识
在RouteConfig类中新建一个类,重写GetRouteData方法,进行一些类似于浏览器监察,判断是否用的是相应版本的浏览器或者哪种浏览器等。
public class MyRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
if (httpContext.Request.UserAgent.Contains("Chrome"))
{
return null;
}
else
{
RouteData routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "Home");
routeData.Values.Add("action", "Refuse");
return routeData;
}
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
throw new NotImplementedException();
}
}
在RegisterRoutes中添加浏览器验证:
routes.Add("browser",new MyRoute());
2.权限验证
新建一个特性类,重写AuthorizeAttribute中的OnAuthorization方法
public class CustomAuthorizeAttribute:AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
//base.OnAuthorization(filterContext);
//Console.WriteLine(filterContext.HttpContext.Request.Url.AbsoluteUri);
//return;
var user = filterContext.HttpContext.Session["CurrentUser"];
if(filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute),true))
{
return;
}
else if(filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute),true))
{
return;
}
else if(user==null||string.IsNullOrEmpty(user.ToString()))
{
filterContext.Result = new RedirectResult("~/Second/Login");
}
else
{
return;
}
}
}
在Global.asax中
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();//注册区域
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//Filter 全局验证
RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//Filter 全局验证
F12进入到FilterConfig中添加全局验证,
filters.Add(new CustomAuthorizeAttribute());
但是这样添加上之后就会使所有的页面,所有的Action都会有验证,对于一些Action或者页面避免验证:就要在相应的位置添加特性AllowAnonymousAttribute。
2.异常处理
添加异常特性类CustomHandleErrorAttribute
public class CustomHandleErrorAttribute:HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
//base.OnException(filterContext);
//Console.WriteLine(filterContext.HttpContext.Request.Url.AbsoluteUri);
//Console.WriteLine(filterContext.Exception.Message);
if(!filterContext.ExceptionHandled)//表示未被别的Filter处理
{
//跳转到错误页
//filterContext.Result = new RedirectResult("~/Second/Login");
filterContext.Result = new ViewResult()
{
ViewName = "~/Views/Shared/Error.cshtml",
ViewData = new ViewDataDictionary<string>(filterContext.Exception.Message)
};
filterContext.ExceptionHandled = true;
}
}
}
同样在FilterConfig中添加全局Filter,
filters.Add(new CustomHandleErrorAttribute());
这样一般的异常都会跳转到错误页面。
但对于一些4XX错误类的异常无法捕获,如果需要这样的处理可以在Global.asax中添加一个全局异常处理:
/// <summary>
/// 全局异常处理,
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Application_Error(object sender,EventArgs e)
{
var ex = Server.GetLastError();
Response.Clear();
Response.Write("This is Error by Global!");
Response.ContentType = "text/html";
Response.End();
}
3.日志记录
新建CustomActionFilterAttribute特性类,继承ActionFilterAttribute
/// <summary>
/// Action 执行前完成 可以检查参数
/// </summary>
/// <param name="filterContext"></param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string record = $"记录事件操作:";
foreach (var value in filterContext.RouteData.Values)
{
record += $"{value.Key}:{value.Value}";
}
record += $"执行开始,操作人:{filterContext.HttpContext.Session["CurrentUser"]},操作时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}。\r\n";
filterContext.HttpContext.Response.Write(record);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write($"This is {nameof(CustomActionFilterAttribute)} {nameof(OnActionExecuted)}");//
//检测浏览器支持的压缩格式
//var request = filterContext.HttpContext.Request;
//var response = filterContext.HttpContext.Response;
//string encoding = request.Headers["Accept-Encoding"];
//if(!string.IsNullOrEmpty(encoding))
//{
// if(encoding.ToLower().Contains("gzip"))
// {
// //要求服务器压缩
// response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
// response.AppendHeader("Contend-encoding", "gzip");
// }
//}
base.OnActionExecuted(filterContext);
}
/// <summary>
/// 在ExecuteResult之前
/// </summary>
/// <param name="filterContext"></param>
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
base.OnResultExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
}
这里没有提供日志的记录具体方法,只提供特性类,只要在里面调用记录日志的方法就可以记录没步骤的操作,操作人,操作时间。