# 第4章：ASP.NET Core HTTP介绍

#### 任务22：课程介绍 <a href="#ren-wu-22-ke-cheng-jie-shao" id="ren-wu-22-ke-cheng-jie-shao"></a>

* 1.HTTP 处理过程
* 2.WebHost 的配置与启动
* 3.Middleware 与管道
* 4.Routing MiddleWare 介绍

#### 任务23：Http请求的处理过程 <a href="#ren-wu-23http-qing-qiu-de-chu-li-guo-cheng" id="ren-wu-23http-qing-qiu-de-chu-li-guo-cheng"></a>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FHLIXUWpEWvqPMGOIk5Hu%2F038.jpg?alt=media\&token=a5c371ad-749f-47e5-962c-3065a9a6d88d)

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FNYazSD1RDeqUg3XafCMY%2F039.jpg?alt=media\&token=bf622070-2333-44e1-ac0a-10ed94cb6fe4)

#### 任务24：WebHost的配置 <a href="#ren-wu-24webhost-de-pei-zhi" id="ren-wu-24webhost-de-pei-zhi"></a>

* 1.覆盖配置文件
* 2.更改启动URL
* 3.IHostingEnvironment
* 4.IApplicationLifetime
* 5.dotnet watch run

```
dotnet new web
```

settings.json

```
{
    "ConnectionStrings":{
        "DefaultConnection":"Server=...;Database=...;"
    }
}
```

Program.cs

```
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration(configureDelegate=>{
                configureDelegate.AddJsonFile("settings.json");
            })
            .UseStartup<Startup>();
```

Startup.cs

```
using Microsoft.Extensions.Configuration;

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Run(async (context) =>
            {
                // await context.Response.WriteAsync("Hello World!");
                // JsonFile
                await context.Response.WriteAsync(configuration["ConnectionStrings:DefaultConnection"]);
            });
        }
```

启动HelloCore，输出结果\
![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FKuKT1zlkvj823lVjHwBF%2F040.jpg?alt=media\&token=f4e95d21-e9cb-4206-adbe-147795de417a)

Program.cs

```
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration(configureDelegate => {
                    //configureDelegate.AddJsonFile("settings.json");
                    configureDelegate.AddCommandLine(args);
                })
                //.UseUrls("http://localhost:5001")
                .UseStartup<Startup>();
```

Startup.cs

```
            app.Run(async (context) =>
            {
                // await context.Response.WriteAsync("Hello World!");
                // JsonFile
                //await context.Response.WriteAsync(configuration["ConnectionStrings:DefaultConnection"]);
                // CommandLine
                await context.Response.WriteAsync($"name={configuration["name"]}");
            });
```

设置应用程序参数<br>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FSEkNp3sQwmKSMk6rgdwD%2F041.png?alt=media\&token=5f1940fe-51de-4bf7-87e1-6b24deb960a5)

启动HelloCore，输出结果\
![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FQ8MqepkVtBWNXMa6i49r%2F042.jpg?alt=media\&token=ec62027a-aa78-4598-b8b2-241480f45931)

#### 任务25：IHostEnvironment和 IApplicationLifetime介绍 <a href="#ren-wu-25ihostenvironment-he-iapplicationlifetime-jie-shao" id="ren-wu-25ihostenvironment-he-iapplicationlifetime-jie-shao"></a>

Startup.cs

```
app.Run(async (context) =>
            {
                await context.Response.WriteAsync($"ContentRootPath = {env.ContentRootPath}");
                await context.Response.WriteAsync($"EnvironmentName = {env.EnvironmentName}");
                await context.Response.WriteAsync($"WebRootPath = {env.WebRootPath}");
            });
```

启动HelloCore，输出结果<br>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2Fw3HC5yy0AkqRT57kks1U%2F043.jpg?alt=media\&token=9389bbc3-4570-45f1-bd79-29c6b5f46272)

Startup.cs

```
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConfiguration configuration, IApplicationLifetime applicationLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            applicationLifetime.ApplicationStarted.Register(() =>
            {
                Console.WriteLine("Started");
            });

            applicationLifetime.ApplicationStopped.Register(() =>
            {
                Console.WriteLine("Stopped");
            });

            applicationLifetime.ApplicationStopped.Register(() =>
            {
                Console.WriteLine("Stopped");
            });

            app.Run(async (context) =>
            {                
                await context.Response.WriteAsync($"ContentRootPath = {env.ContentRootPath}");
                await context.Response.WriteAsync($"EnvironmentName = {env.EnvironmentName}");
                await context.Response.WriteAsync($"WebRootPath = {env.WebRootPath}");
            });
        }
```

启动HelloCore，输出结果<br>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2Fw3HC5yy0AkqRT57kks1U%2F043.jpg?alt=media\&token=9389bbc3-4570-45f1-bd79-29c6b5f46272)

我心中的ASP.NET Core 新核心对象WebHost（一）：

<http://www.jessetalk.cn/2017/11/11/aspnet-core-object-webhost/#comment-194>

我心中的ASP.NET Core 新核心对象WebHost（二）：

<http://www.jessetalk.cn/2017/11/14/aspnet-core-object-webhost-build/>

#### 任务26：dotnet watch run 和attach到进程调试 <a href="#ren-wu-26dotnetwatchrun-he-attach-dao-jin-cheng-tiao-shi" id="ren-wu-26dotnetwatchrun-he-attach-dao-jin-cheng-tiao-shi"></a>

New Terminal

```
dotnet new web --name HelloCore
```

F5 Start Debug

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2Fm7jI49Y9FsUJAwgRVnUf%2F044.png?alt=media\&token=55bb4f3a-8b6d-4723-b0f7-f4843a010bbc)

在csproj 的 ItemGroup 添加引用

```
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
```

New Terminal

```
dotnet restore
dotnet watch run
```

修改代码保存后会自动重启

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FLYWQmjTXje6Y5zQO6LGy%2F045.png?alt=media\&token=b8d48232-5264-456a-8290-c785bbcfb64d)

浏览器刷新即可看到更新结果

attach到进程调试

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2F2fcWRMaumPcBS4OgJHAC%2F046.png?alt=media\&token=a90127c4-29b5-4f2f-989d-40aceb7a02c3)

#### 任务27：Middleware管道介绍 <a href="#ren-wu-27middleware-guan-dao-jie-shao" id="ren-wu-27middleware-guan-dao-jie-shao"></a>

* 1.Middleware 与管道的概念
* 2.用 Middleware 来组成管道实践
* 3.管道的实现机制（RequestDelegate 与 ApplicationBuilder）

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2F7QbLoV056lvaYxJ94kyM%2F047.jpg?alt=media\&token=a5ac763b-b268-42c9-886e-9c018d406073)

startup.cs

```
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            // 添加一个中间件，传一个名字为next的request delegate
            app.Use(async (context,next)=>{
                await context.Response.WriteAsync("1: before start...");
                await next.Invoke();
            });

            // 接收一个RequestDelegate，返回一个RequestDelegate
            app.Use(next=>{
                return (context)=>{
                    context.Response.WriteAsync("2: in the middle of start..");
                    return next(context);
                };
            });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("3: start...");
            });
        }
```

启动项目，输出结果

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2F15NXTYF8YvR2C12OvLdq%2F048.jpg?alt=media\&token=7c870fde-e903-42eb-a9f9-8650bf1d15e6)

```
// 如果不调用next，则管道终止，不会输出"3: start..."
            app.Use(next=>{
                return (context)=>{
                    return context.Response.WriteAsync("2: in the middle of start..");
                    //return next(context);
                };
            });
```

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2Ftlm3H77Ci4qJXGX7jgjQ%2F049.jpg?alt=media\&token=43cb13d9-92c7-485c-8960-cc3109d0d1e6)

```
        // 使用Map构建路由，通过localhost:5000/task访问
        app.Map("/task", taskApp=>{
            taskApp.Run(async context=>{
                await context.Response.WriteAsync("this is a task");
            });
        });

        // 添加一个中间件，传一个名字为next的request delegate
        app.Use(async (context,next)=>{
            await context.Response.WriteAsync("1: before start...");
            await next.Invoke();
        });

        // 接收一个RequestDelegate，返回一个RequestDelegate
        // 如果不调用next，则管道终止，不会输出"3: start..."
        app.Use(next=>{
            return (context)=>{
                context.Response.WriteAsync("2: in the middle of start..");
                return next(context);
            };
        });

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("3: start...");
        });
```

访问 <https://localhost:5001/task>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FMBHSvR8q3L6oww4ukS33%2F050.jpg?alt=media\&token=3c181569-6e54-43d2-907e-90673ac3035e)

#### 任务28：RequestDelegate管道实现思路 <a href="#ren-wu-28requestdelegate-guan-dao-shi-xian-si-lu" id="ren-wu-28requestdelegate-guan-dao-shi-xian-si-lu"></a>

* 1.RequestDelegate
* 2.ApplicationBuilder：多个RequestDelegate拼接

```
// 添加一个中间件，传一个名字为next的RequestDelegate
app.Use(async (context,next)=>{
    await context.Response.WriteAsync("1: before start...");// 完成自己处理
    await next.Invoke();// 调用下一步
});

// 封装一个function交给ApplicationBuilder处理
app.Use(next=>{
    return (context)=>{
        context.Response.WriteAsync("2: in the middle of start..");
        return next(context);
    };
});
```

#### 任务29：自己动手构建RequestDelegate管道 <a href="#ren-wu-29-zi-ji-dong-shou-gou-jian-requestdelegate-guan-dao" id="ren-wu-29-zi-ji-dong-shou-gou-jian-requestdelegate-guan-dao"></a>

新建一个控制台程序

```
dotnet new console --name MyPipeline
```

新建一个类RequestDelegate.cs

```
using System;
using System.Threading.Tasks;

namespace MyPipeline
{
    public delegate Task RequestDelegate(Context context);
}
```

新建一个类Context.cs

```
using System;
using System.Threading.Tasks;

namespace MyPipeline
{
    public class Context
    {
        
    }
}
```

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MyPipeline
{
    class Program
    {
        public static List<Func<RequestDelegate,RequestDelegate>> 
        _list = new List<Func<RequestDelegate, RequestDelegate>>();
        static void Main(string[] args)
        {
            Use(next=>{
                return context=>{
                    Console.WriteLine("1");
                    return next.Invoke(context);
                };
            });

            Use(next=>{
                return context=>{
                    Console.WriteLine("2");
                    return next.Invoke(context);
                };
            });

            RequestDelegate end = (Context)=>{
                Console.WriteLine("end...");
                return Task.CompletedTask;
            };

            _list.Reverse();
            foreach(var middleware in _list)
            {
                end = middleware.Invoke(end);
            }

            end.Invoke(new Context());
            Console.ReadLine();
        }

        public static void Use(Func<RequestDelegate,RequestDelegate> middleware)
        {
            _list.Add(middleware);
        }
    }
}
```

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2Ftgb03VDkvifl6ZvcuYj2%2F051.jpg?alt=media\&token=bdd2941f-6645-4606-9024-d1d59f06fdf3)

在任何一个Middleware可以结束管道

```
            Use(next=>{
                return context=>{
                    Console.WriteLine("1");
                    //return next.Invoke(context);
                    return Task.CompletedTask;// 结束管道调用，只输出1
                };
            });
```

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FFZ1DVKBVgxZ8dvejs1Nf%2F052.jpg?alt=media\&token=e4d84abe-c238-4887-95cf-9ac4aa1befad)

#### 任务30：RoutingMiddleware介绍以及MVC引入 <a href="#ren-wu-30routingmiddleware-jie-shao-yi-ji-mvc-yin-ru" id="ren-wu-30routingmiddleware-jie-shao-yi-ji-mvc-yin-ru"></a>

```
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace HelloCore
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRouting();// 添加依赖注入配置
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            // 通过localhost:5000/action访问
            app.UseRouter(builder=>builder.MapGet("action", async context=>{
                await context.Response.WriteAsync("this is a action");
            }));

            // 使用Map构建路由，通过localhost:5000/task访问
            app.Map("/task", taskApp=>{
                taskApp.Run(async context=>{
                    await context.Response.WriteAsync("this is a task");
                });
            });

            // 添加一个中间件，传一个名字为next的request delegate
            app.Use(async (context,next)=>{
                await context.Response.WriteAsync("1: before start...");
                await next.Invoke();
            });

            // 如果不调用next，则管道终止，不会输出"3: start..."
            app.Use(next=>{
                return (context)=>{
                    return context.Response.WriteAsync("2: in the middle of start..");
                    //return next(context);
                };
            });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("3: start...");
            });
        }
    }
}
```

访问 <https://localhost:5001/action>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2FwN3S40OOKBdIkbP3ApzZ%2F053.jpg?alt=media\&token=c5c56bd2-2db1-4651-ad2c-73f641ecbf37)

使用UseRouter方法2

```
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace HelloCore
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRouting();// 添加依赖注入配置
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            // 使用UseRouter方法2
            // 通过localhost:5000/action访问
            RequestDelegate handler = context=>context.Response.WriteAsync("this is a action");
            var route = new Route(
                new RouteHandler(handler),
                "action",
                app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>()
            );

            app.UseRouter(route);

            // 使用UseRouter方法1
            // 通过localhost:5000/action访问
            app.UseRouter(builder=>builder.MapGet("action", async context=>{
                await context.Response.WriteAsync("this is a action");
            }));

            // 使用Map构建路由，通过localhost:5000/task访问
            app.Map("/task", taskApp=>{
                taskApp.Run(async context=>{
                    await context.Response.WriteAsync("this is a task");
                });
            });

            // 添加一个中间件，传一个名字为next的request delegate
            app.Use(async (context,next)=>{
                await context.Response.WriteAsync("1: before start...");
                await next.Invoke();
            });

            // 如果不调用next，则管道终止，不会输出"3: start..."
            app.Use(next=>{
                return (context)=>{
                    return context.Response.WriteAsync("2: in the middle of start..");
                    //return next(context);
                };
            });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("3: start...");
            });
        }
    }
}
```

访问 <https://localhost:5001/action>

![](https://256343630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Flyk5lHXG8Cnqf7q1KuaO%2Fuploads%2F3LhmhIUTy6mpHESgzsXw%2F054.jpg?alt=media\&token=309dcee8-59ca-4bfc-a176-4d9651ccf617)

**RountingMiddleware介绍**

```
var routeHandler = new RouteHandler(context=>context.Response.WriteAsync("test"));

var route = new Route(routeHandler);

new RouteMiddleware(route)

RouteMiddleware.Invoke(httpContext)

_route.RouteAsync(context)

routeMatch(RouteContext)

OnRouteMatched(RouteContext)
```
