(精华)2020年8月20日 ASP.NET MVC 管道模型详解

ASP.NET MVC管道模型图
在这里插入图片描述
在这里插入图片描述

HttpModule管道

public class BaseModule : IHttpModule
{
    /// <summary>
    /// Init方法仅用于给期望的事件注册方法
    /// </summary>
    /// <param name="httpApplication"></param>
    public void Init(HttpApplication httpApplication)
    {
        httpApplication.BeginRequest += new EventHandler(context_BeginRequest);//Asp.net处理的第一个事件,表示处理的开始
        //context.AuthenticateRequest	//验证请求,一般用来取得请求用户的信息
        //context.PostAuthenticateRequest	已经获取请求用户的信息
        //context.AuthorizeRequest	授权,一般用来检查用户的请求是否获得权限
        //context.PostAuthorizeRequest	用户请求已经得到授权
        //context.ResolveRequestCache	获取以前处理缓存的处理结果,如果以前缓存过,那么,不必再进行请求的处理工作,直接返回缓存结果
        //context.PostResolveRequestCache	已经完成缓存的获取操作
        //context.PostMapRequestHandler	已经根据用户的请求,创建了处理请求的处理器对象
        //context.AcquireRequestState	取得请求的状态,一般用于Session
        //context.PostAcquireRequestState	已经取得了Session
        //context.PreRequestHandlerExecute	准备执行处理程序
        //context.PostRequestHandlerExecute	已经执行了处理程序
        //context.ReleaseRequestState	释放请求的状态
        //context.PostReleaseRequestState	已经释放了请求的状态
        //context.UpdateRequestCache	更新缓存
        //context.PostUpdateRequestCache	已经更新了缓存
        //context.LogRequest	请求的日志操作
        //context.PostLogRequest	已经完成了请求的日志操作
        httpApplication.EndRequest += new EventHandler(context_EndRequest);//本次请求处理完成
    }

    // 处理BeginRequest 事件的实际代码
    private void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;
        string extension = Path.GetExtension(context.Request.Url.AbsoluteUri);
        if (string.IsNullOrWhiteSpace(extension) && !context.Request.Url.AbsolutePath.Contains("Verify"))
        {
            context.Response.Write(string.Format("<h1 style='color:#00f'>来自BaseModule 的处理,{0}请求到达</h1><hr>", DateTime.Now.ToString()));
        }

        //处理地址重写
        if (context.Request.Url.AbsolutePath.Equals("/Pipe/Some", StringComparison.OrdinalIgnoreCase))
            context.RewritePath("/Pipe/Handler");
    }

    // 处理EndRequest 事件的实际代码
    private void context_EndRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;
        string extension = Path.GetExtension(context.Request.Url.AbsoluteUri);
        if (string.IsNullOrWhiteSpace(extension) && !context.Request.Url.AbsolutePath.Contains("Verify"))
            context.Response.Write(string.Format("<hr><h1 style='color:#f00'>来自BaseModule的处理,{0}请求结束</h1>", DateTime.Now.ToString()));
    }

    public void Dispose()
    {

    }
}

把上面HttpModule那个类注册到配置文件中

<system.webServer>
  <!--集成模式使用这个-->
  <modules>
    <remove name="TelemetryCorrelationHttpModule" />

    <!--<remove name="WindowsAuthentication"/>
    <remove name="FormsAuthentication"/>
    <remove name="PassportAuthentication"/>-->
    
    <add name="CustomHttpModule" type="MVC5.Utility.Pipeline.CustomHttpModule,MVC5"/>

    <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="integratedMode,managedHandler" />
    <remove name="ApplicationInsightsWebTracking" />
    <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
  </modules>
  <validation validateIntegratedModeConfiguration="false" />
</system.webServer>

对于modul中注册的自定义事件需要在全局文件中执行代码如下

public class MvcApplication : System.Web.HttpApplication
{
    private Logger logger = new Logger(typeof(MvcApplication));
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();//注册区域
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//注册全局的Filter
        RouteConfig.RegisterRoutes(RouteTable.Routes);//注册路由
        BundleConfig.RegisterBundles(BundleTable.Bundles);//合并压缩 ,打包工具 Combres
        ControllerBuilder.Current.SetControllerFactory(new ElevenControllerFactory());

        this.logger.Info("网站启动了。。。");
    }
    /// <summary>
    /// 全局式的异常处理,可以抓住漏网之鱼
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Application_Error(object sender, EventArgs e)
    {
        Exception excetion = Server.GetLastError();
        this.logger.Error($"{base.Context.Request.Url.AbsoluteUri}出现异常");
        Response.Write("System is Error....");
        Server.ClearError()
        //Response.Redirect
        //base.Context.RewritePath("/Home/Error?msg=")
    }

	//这个就算modul里注册事件的执行方法
    protected void CustomHttpModule_CustomHttpModuleHandler(object sender, EventArgs e)
    {
        this.logger.Info("this is CustomHttpModule_CustomHttpModuleHandler");
    }
    /// <summary>
    /// 会在系统新增一个session时候触发
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Session_Start(object sender, EventArgs e)
    {
        HttpContext.Current.Application.Lock();
        object oValue = HttpContext.Current.Application.Get("TotalCount");
        if (oValue == null)
        {
            HttpContext.Current.Application.Add("TotalCount", 1);
        }
        else
        {
            HttpContext.Current.Application.Add("TotalCount", (int)oValue + 1);
        }
        HttpContext.Current.Application.UnLock();
        this.logger.Debug("这里执行了Session_Start");
    }
    /// <summary>
    /// 系统释放一个session的时候
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Session_End(object sender, EventArgs e)
    {
        this.logger.Debug("这里执行了Session_End");
    }
}

HttpHandler请求头

/// <summary>
/// 防盗链:不允许盗链; 
/// 盗链:在A 网站中 请求了B网站的资源; 
/// </summary>
public class ImageHandler : IHttpHandler
{
    #region IHttpHandler Members

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        // 如果UrlReferrer为空,则显示一张默认的禁止盗链的图片
        if (context.Request.UrlReferrer == null || context.Request.UrlReferrer.Host == null)
        {    //大部分都是爬虫
            context.Response.ContentType = "image/JPEG";
            context.Response.WriteFile("/Content/Image/Forbidden.jpg");
        }
        else
        {
            // 如果 UrlReferrer中不包含自己站点主机域名,则显示一张默认的禁止盗链的图片
            if (context.Request.UrlReferrer.Host.Contains("localhost"))
            {
                // 获取文件服务器端物理路径
                string FileName = context.Server.MapPath(context.Request.FilePath);
                context.Response.ContentType = "image/JPEG";
                context.Response.WriteFile(FileName);
            }
            else
            {
                context.Response.ContentType = "image/JPEG";
                context.Response.WriteFile("/Content/Image/Forbidden.jpg");
            }
        }
    }

    #endregion
}
/// <summary>
/// 注册handlerfactory
/// 可以为不同的后缀指定不同的handler
/// aspx的ioc就可以从这个地方注入
/// </summary>
public class ImageHandlerFactory : IHttpHandlerFactory
{
    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
        string path = context.Request.PhysicalPath;
        if (Path.GetExtension(path).Equals(".gif"))
        {
            return new ImageHandler();
        }
        else if (Path.GetExtension(path) == ".png")
        {
            return new ImageHandler();
        }
        else
        {
            return new ImageHandler();
        }
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
    }
}

在配置文件中加上如下代码

<system.webServer>
  <!--集成模式使用这个-->
  <handlers>
    <!--<add name="config" verb="*" path="*.config" type="System.Web.StaticFileHandler"/>-->
    <!--带会儿留个后门-->
    <add name="rtmp" verb="*" path="*.rtmp" type="XT.MVC5.Utility.Pipeline.CustomRTMPHandler,XT.MVC5"/>
    <add name="gif" path="*.gif" verb="*" type="XT.Web.Core.PipeLine.ImageHandler,XT.Web.Core" />
    <add name="png" path="*.png" verb="*" type="XT.Web.Core.PipeLine.ImageHandler,XT.Web.Core" />
    <add name="jpg" path="*.jpg" verb="*" type="XT.Web.Core.PipeLine.ImageHandler,XT.Web.Core" />
    <add name="jpeg" path="*.jpeg" verb="*" type="XT.Web.Core.PipeLine.ImageHandler,XT.Web.Core" />
  </handlers>
  <validation validateIntegratedModeConfiguration="false" />
</system.webServer>

在到路由配置中忽略handlers中定义的结尾名称,在请求中出现结尾就会按照配置文件定义交给相应类处理

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    //忽略路由  正则表达式  {resource}表示变量   a.axd/xxxx 
}

Route路由事件

public class CustomRoute : RouteBase
{
    /// <summary>
    /// 如果是Chrome/74.0.3729.169 版本,允许正常访问
    /// 否则 跳转提示页
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        //httpContext.Request.Url.AbsoluteUri
        if (httpContext.Request.UserAgent.Contains("Chrome/74.0.3729.169"))
        {
            return null;//继续后面的
        }
        else
        {
            RouteData routeData = new RouteData(this, new MvcRouteHandler());//还是走mvc流程
            routeData.Values.Add("controller", "pipe");
            routeData.Values.Add("action", "refuse");
            return routeData;//中断路由匹配
        }
    }
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        return null;
    }
}

public class CustomMvcRouteHandler : MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new CustomHttpHandler();
    }
}

public class CustomHttpHandler : IHttpHandler
{
    public bool IsReusable => true;

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/html";
        context.Response.WriteFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web.config"));
        //看日志
    }
}

在全局路由配置添加如下代码

routes.Add("config", new Route("xt/{path}", new CustomMvcRouteHandler()));

View视图引擎

在全局文件加如下代码

protected void Application_Start()
{
    string engineDescription = string.Join(",", ViewEngines.Engines.ToList().Select(v => v.ToString()));
    //清除默认视图引擎
    ViewEngines.Engines.Clear();
    //添加自己视图引擎
    ViewEngines.Engines.Add(new CustomViewEngine());
}

视图引擎的类

/// <summary>
/// 解决方案:
/// a 覆写的是FindView而不是CreateView(迟了),而且一定得set回去 Materal--66.6红包
/// b CreateView时直接修改path(狠人)   RGB--66.6红包
/// 注意不同的路径如_ViewStart
/// </summary>
public class CustomViewEngine : RazorViewEngine
{
    #region 构造函数
    public ElevenCustomViewEngine() : this(null)
    {
    }
    public ElevenCustomViewEngine(IViewPageActivator viewPageActivator) : base(viewPageActivator)
    {
        this.SetEngine("");
    }
    #endregion

    #region A
    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
        //if (controllerContext.HttpContext.Request.UserAgent.Contains("Chrome/74.0.3729.169"))
        //{
        //    this.SetEngine("Chrome");
        //}
        //else
        //{
        //    this.SetEngine("");//一定得有,因为只有一个Engine实例
        //}
        return base.FindView(controllerContext, viewName, masterName, useCache);
    }

    public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
    {
        //if (controllerContext.HttpContext.Request.UserAgent.Contains("Chrome/74.0.3729.169"))
        //{
        //    this.SetEngine("Chrome");
        //}
        //else
        //{
        //    this.SetEngine("");
        //}
        return base.FindPartialView(controllerContext, partialViewName, useCache);
    }
    #endregion


    #region B
    /// <summary>
    /// 
    /// </summary>
    /// <param name="controllerContext">可以为所欲为</param>
    /// <param name="partialPath"></param>
    /// <returns></returns>
    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
    {
        if (controllerContext.HttpContext.Request.UserAgent.Contains("Chrome/74.0.3729.169"))
        {
            partialPath = partialPath.Replace("/Views/", "/ChromeViews/");
        }
        return base.CreatePartialView(controllerContext, partialPath);
    }
    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
    {
        if (controllerContext.HttpContext.Request.UserAgent.Contains("Chrome/74.0.3729.169"))
        {
            viewPath = viewPath.Replace("/Views/", "/ChromeViews/");
            masterPath = masterPath.Replace("/Views/", "/ChromeViews/");
        }
        return base.CreateView(controllerContext, viewPath, masterPath);
    }
    #endregion
    /// <summary>
    /// 把模板给换了
    /// </summary>
    /// <param name="browser"></param>
    private void SetEngine(string browser)
    {
        if (!string.IsNullOrWhiteSpace(browser))
        {
            base.AreaViewLocationFormats = new string[]
                        {
            "~/Areas/{2}/"+browser+"Views/{1}/{0}.cshtml",
            "~/Areas/{2}/"+browser+"Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/"+browser+"Views/Shared/{0}.cshtml",
            "~/Areas/{2}/"+browser+"Views/Shared/{0}.vbhtml"
                        };
            base.AreaMasterLocationFormats = new string[]
            {
            "~/Areas/{2}/"+browser+"Views/{1}/{0}.cshtml",
            "~/Areas/{2}/"+browser+"Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/"+browser+"Views/Shared/{0}.cshtml",
            "~/Areas/{2}/"+browser+"Views/Shared/{0}.vbhtml"
            };
            base.AreaPartialViewLocationFormats = new string[]
            {
            "~/Areas/{2}/"+browser+"Views/{1}/{0}.cshtml",
            "~/Areas/{2}/"+browser+"Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/"+browser+"Views/Shared/{0}.cshtml",
            "~/Areas/{2}/"+browser+"Views/Shared/{0}.vbhtml"
            };
            base.ViewLocationFormats = new string[]
            {
            "~/"+browser+"Views/{1}/{0}.cshtml",
            "~/"+browser+"Views/{1}/{0}.vbhtml",
            "~/"+browser+"Views/Shared/{0}.cshtml",
            "~/"+browser+"Views/Shared/{0}.vbhtml"
            };
            base.MasterLocationFormats = new string[]
            {
            "~/"+browser+"Views/{1}/{0}.cshtml",
            "~/"+browser+"Views/{1}/{0}.vbhtml",
            "~/"+browser+"Views/Shared/{0}.cshtml",
            "~/"+browser+"Views/Shared/{0}.vbhtml"
            };
            base.PartialViewLocationFormats = new string[]
            {
            "~/"+browser+"Views/{1}/{0}.cshtml",
            "~/"+browser+"Views/{1}/{0}.vbhtml",
            "~/"+browser+"Views/Shared/{0}.cshtml",
            "~/"+browser+"Views/Shared/{0}.vbhtml"
            };
        }
        else
        {
            base.AreaViewLocationFormats = new string[]
       {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.vbhtml"
       };
            base.AreaMasterLocationFormats = new string[]
            {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            base.AreaPartialViewLocationFormats = new string[]
            {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            base.ViewLocationFormats = new string[]
            {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml"
            };
            base.MasterLocationFormats = new string[]
            {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml"
            };
            base.PartialViewLocationFormats = new string[]
            {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml"
            };
            base.FileExtensions = new string[]
            {
            "cshtml",
            "vbhtml"
            };
        }
    }
}
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:上身试试 返回首页