当在浏览器键入URL后会发生哪些事情(ASP.NET Core篇)?

2019/10/11

25

前面文章 当在浏览器键入URL后会发生哪些事情(浏览器篇)?当在浏览器键入URL后会发生哪些事情(网络篇)? 分别介绍了一些知识,而这篇文章主要是讲解 ASP.NET Core 是如何处理请求与响应的。

由于我没有在网上找到权威的资料,加上个人水平有限,因此这篇文章的水货非常多,也非常肤浅,如有错误,欢迎指正。

HttpContext

在 ASP.NET Core 中,HttpContextControllerBase 的公开属性,我们所写的所有 Controller 全都是 ControllerBase 的子类,因此,我们在 Action 中可以使用 HttpContext 对象。

HttpContext 类定义了我们熟悉的对象,常见的如下

而我们所熟知的 ASP.NET Core MVC 框架的很多功能都是基于 HttpContext 和 HTTP 协议来完成的,帮助我们更快捷,安全的开发 Web 应用程序。

当请求报文信息到达服务端程序后,程序会构建 HttpContext 对象,服务端程序会解析请求报文数据,创建 Request 对象,QueryStringPathMethodCookies 等等都会被赋值,以便后续的使用。

MVC 中间件

ASP.NET Core MVC 使用了中间件思想,废弃了 ASP.NET MVC 4.x 中的 HttpModuleHttpHanddler 思想。

中间件请求管道

Startup.Configure 方法添加中间件组件的顺序定义了针对请求调用这些组件的顺序,以及响应的相反顺序。 此排序对于安全性、性能和功能至关重要

以下代码是微软 ASP.NET Core v3.0 文档中间件顺序示例代码

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseSession();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

MVC 过滤器

请求历尽千辛万苦,匹配上了路由模板后,会交由 ASP.NET Core MVC 对应的 ControllerAction 执行。我们都知道在 ControllerAction 上都可以追加上特性标签(Atrribute),ASP.NET Core MVC 率先会调用的过滤器是AuthorizeAttribute,如果请求通过了 AuthorizeAttribute 后,接下来会调用 IActionFilter,模型绑定在这期间完成。

public class MySampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}

如果 ASP.NET Core MVC 框架中,由于用户的代码发生的错误,ASP.NET Core MVC 框架会调用 ExceptionFilterAttribute

当一切正常时,ASP.NET Core MVC 框架最后会调用 IResultFilter

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation("Header added: {HeaderName}", headerName);
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
    }
}

OnResultExecuting 执行完成后 OnResultExecuted 执行完成前,ASP.NET Core MVC 框架会根据返回的内容,设置 Response Status Code、Response Content、响应头、等等信息。

如果是 Razor 页面,根据 cshtml 文件动态渲染 html 也在这期间完成。

ASP.NET Core MVC 会沿着中间件以此往回传递,最后 ASP.NET Core 所做的任务就完成了,响应的结果经由 TCP 传递给客户端浏览器进行解析。

评论