Asp.Net Mvc 运行机制原理分析

3 篇文章 0 订阅

最近一段时间接手过的项目都是基于Asp.Net的,以前对aspnet运行机制有一个大概的了解,总觉得不够透彻,按自己的理解来分析一下。

Asp.Net 运行机制

理解mvc运行原理的前提是要了解aspnet运行原理,这方面网上资料多如牛毛,我这里就大致说一下aspnet生命周期

Http请求到IIS后,如果是静态资源则IIS读取后返回客户端,动态请求被isap.dll 转发自net托管平台处理,首先HttpRuntime中创建Application,它是整个请求生命周期的开始,运行在单独的Appdomain中,在Application 中顺序调用所有已注册的Ihttpmodule,在IHttpModule中可以 "短路"(终止后续IHttpModule的执行),很多Web框架都是在这里做了文章,包括大名鼎鼎的Asp.Net Mvc, IHttpModule执行完后 最终请求被交给IHttpHandler, 在Handler中执行完毕后 再一层层返回到客户端。

 

ASP.NET MVC5 运行原理

这是来自微软官方的运行原理图

当前请求到达 IIS服务器后,同样动态请求被转发到net平台,在管道执行过程中(IHttpModule),有一个特殊的IHttpModule

它就是 UrlRoutingModule ,MVC从这里就开始了。

它 根据当前的HttpContext封装HttpContextWrapper,从Route路由表中取出和当前URL匹配的路由数据(RouteData),接着生成RequestContext对象,然后创建IHttpHandler这里是MvcHandler在MvcHandler中完成了图中处理管线的所有操作。

下面从源码级分析一次请求处理流程

当请求到达路由Module时,创建MvcHandler并将封装好的RequestContext请求上下文传递给它

public MvcHandler(RequestContext requestContext)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }

            RequestContext = requestContext;
        }

执行MvcHandler的BeginProcessRequest方法,创建HttpContextWrapper

protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
        {
            HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
            return BeginProcessRequest(httpContextBase, callback, state);
        }

在BeginProcess中实例化了Controller并执行对应的Action等,做了很多工作,一步步来分析

protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
        {
            IController controller;
            IControllerFactory factory;
            ProcessRequestInit(httpContext, out controller, out factory);

            IAsyncController asyncController = controller as IAsyncController;
            if (asyncController != null)
            {
                // asynchronous controller

                // Ensure delegates continue to use the C# Compiler static delegate caching optimization.
                BeginInvokeDelegate<ProcessRequestState> beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState, ProcessRequestState innerState)
                {
                    try
                    {
                        return innerState.AsyncController.BeginExecute(innerState.RequestContext, asyncCallback, asyncState);
                    }
                    catch
                    {
                        innerState.ReleaseController();
                        throw;
                    }
                };

                EndInvokeVoidDelegate<ProcessRequestState> endDelegate = delegate(IAsyncResult asyncResult, ProcessRequestState innerState)
                {
                    try
                    {
                        innerState.AsyncController.EndExecute(asyncResult);
                    }
                    finally
                    {
                        innerState.ReleaseController();
                    }
                };
                ProcessRequestState outerState = new ProcessRequestState() 
                {
                    AsyncController = asyncController, Factory = factory, RequestContext = RequestContext
                };
                
                SynchronizationContext callbackSyncContext = SynchronizationContextUtil.GetSynchronizationContext();
                return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, outerState, _processRequestTag, callbackSyncContext: callbackSyncContext);
            }
            else
            {
                // synchronous controller
                Action action = delegate
                {
                    try
                    {
                        controller.Execute(RequestContext);
                    }
                    finally
                    {
                        factory.ReleaseController(controller);
                    }
                };

                return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag);
            }
        }

在ProcessRequestInit 中,

首先在http响应报文中添加mvc版本信息

AddVersionHeader(httpContext);

从本次请求的路由数据中得到Controller(控制器)名称

//得到控制器名称
string controllerName = RequestContext.RouteData.GetRequiredString("controller");

//从默认的控制器工厂创建控制器实例
factory = ControllerBuilder.GetControllerFactory();
            controller = factory.CreateController(RequestContext, controllerName);
            if (controller == null)
            {
                throw new InvalidOperationException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        MvcResources.ControllerBuilder_FactoryReturnedNull,
                        factory.GetType(),
                        controllerName));
            }

实例化后的Controller

在这个实例化的控制器中,可以拿到很多相关的请求对象 Request Respone Model 等等,

接着如果Controller是异步则异步执行BeginExecute,否则直接执行Execute

Execute方法中执行注册的过滤器(Filter),然后通过反射调用我们的Action,执行完后返回IActionResult,这个IActionResult就是返回给客户端数据包装对象(可能不太贴切)。

处理完成后会执行factory.ReleaseController(controller); 以释放Controller

至此一次http请求在mvc中处理完毕。

有错误的地方望指正。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果在运行 ASP.NET MVC 应用程序后没有弹出网页,可能是由于以下几个原因: 1. 端口被占用:请确保你的应用程序使用的端口没有被其他程序占用。你可以尝试更改应用程序的端口号来解决该问题。在 Visual Studio 中,你可以右键单击项目,选择 "属性",然后在 "Web" 选项卡中更改端口号。 2. 项目没有设置为启动项目:请确保你的 ASP.NET MVC 项目已设置为启动项目。在 Visual Studio 中,你可以右键单击项目,选择 "设为启动项目"。 3. IIS Express 未正确配置:在某些情况下,IIS Express 可能未正确配置,导致无法打开网页。你可以尝试重新安装 IIS Express 或更新 Visual Studio。 4. 防火墙或安全软件阻止访问:请确保你的防火墙或安全软件没有阻止应用程序的访问。你可以尝试禁用防火墙或暂时关闭安全软件来测试是否能够打开网页。 5. 项目中存在错误:如果你的应用程序中存在编译错误或运行时错误,可能会导致网页无法正常打开。请检查 Visual Studio 中的错误列表和输出窗口,以查找并解决任何错误。 6. 缺少依赖项或配置错误:如果你的应用程序依赖于某些第三方库或组件,可能需要确保这些依赖项已正确安装并配置。请检查你的项目文件和应用程序配置文件,确保所有必需的依赖项和配置已正确设置。 如果你尝试了上述解决方法仍然无法解决问题,建议逐步排除问题。可以尝试创建一个简单的 ASP.NET MVC 项目,确保它可以正常运行。随后,逐步将你的代码和配置迁移到新项目中,以确定问题出现的具体原因。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值