Asp.Net Core 入門(二)——Startup.cs作了什麼

  上篇介紹了Program.cs中Main作了什麼,這篇咱們來討論下Startup.cs它又作了什麼呢?html

  咱們新建一個Asp.Net Core Mvc項目,先來開一下Startup的代碼ios

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

  Startup包含兩個方法,咱們先來分析一下ConfigureServices。經過方法上面的註釋能夠看到,這個方法是被.Net運行時調用的,實際上Asp.Net Core提供了內置的IOC容器,此方法就是用來將咱們本身的服務Service注入到Ioc容器當中。那麼如何注入呢?固然是利用該方法的參數IServiceCollection進行注入。若是是咱們自定義的Service,可使用services.AddTransient<IStudentRepository,MockStudentRepository>()或其餘的兩種方式Singleton/Scoped來注入,具體區別看下面代碼。若是是注入.Net Core自帶的,通常是使用AddMvc,AddCors()。web

      public void ConfigureServices(IServiceCollection services)
        {
            //單例注入,建立的對象在全部的地方全部的請求會話建立的都是相同
            services.AddSingleton<IStudentRepository, MockStudentRepository>();

            //瞬時注入,每次都建立一個新的對象
            services.AddTransient<IStudentRepository, MockStudentRepository>();

            //做用域注入,建立的對象在同一個請求會話時是相同的
            services.AddScoped<IStudentRepository, MockStudentRepository>();

            //注入MVC模塊,包含MvcCore和經常使用第三方庫的服務和方法
            services.AddMvc(); 

            //只包含核心的Mvc功能
            services.AddMvcCore();
        }

  接下來咱們來看一下另外一個方法Configure。它是用來配置Asp.Net Core Mvc的Http請求管道的。Asp.Net Core的http請求管道與咱們以前的Asp.Net Mvc的請求管道有着很大的差異,它引入了中間件的概念,更像是一種責任鏈的模式。json

  如今咱們就先來分析一下,參數IHostingEnvironment env,顧名思義是web宿主的環境變量相關的。在咱們的實際開發中,咱們經常會將咱們的環境分紅:開發環境development,繼承環境integration,測試環境testing,預發佈環境staging,生產環境production。那這個環境是怎麼配置的呢?實際上它是經過 ASPNETCORE_ENVIRONMENT 這個環境變量來配置運行時的環境的。cookie

  通常咱們的配置遵循:app

  一、開發機器上,能夠在launchingsetting.json文件中設置該環境變量async

  二、在預發佈環境staging或生產環境production下,儘可能將該變量設置在操做系統中的環境變量裏,由於上篇咱們也講到,Asp.Net Core啓動讀取變量配置的時候是會依次覆蓋的。測試

  三、除了Asp.Net Core提供的development,staging,production外,咱們能夠定義其餘的環境,經過調用 env.IsEnvironment("自定義的環境變量");來判斷是否處於此環境。ui

  通常咱們能夠配置開發環境下顯示錯誤的方式以下面代碼。this

if (env.IsDevelopment())
{
     DeveloperExceptionPageOptions developerExceptionPageOptions = new DeveloperExceptionPageOptions();
     developerExceptionPageOptions.SourceCodeLineCount = 50; //異常顯示行數
     app.UseDeveloperExceptionPage();  //開發者異常頁面
}

  在咱們繼續往下看代碼以前,先來了解一下Asp.Net Core的中間件這個概念。

  中間件是組裝到應用程序管道中以處理請求和響應的軟件,Asp.Net Core自帶了不少的中間件,能夠看下下圖展現的中間件,能夠看到請求通過Logging -> StaticFiles -> MVC後處理完再從MVC -> StaticFiles -> Logging返回給調用方。

  其中MVC爲終端中間件,終端中間件表示執行完這個中間件的時候就已經結束了,不會再往下調用其餘的管道中間件了,這也是咱們建立完項目後看到最後一個是app.UseMvc的緣由。

  關於中間件咱們須要注意的:

  一、中間件能夠同時被訪問和請求

  二、能夠處理請求後,將請求傳遞給下一個中間件

  三、能夠處理請求後,使管道短路

  四、能夠處理傳出響應

  五、中間件是按照添加的順序執行的

   如今咱們來具體分析下Configure裏面是怎麼配置管道的。IApplicationBuilder app 參數爲咱們提供了不少擴展方法,經過這些方法能夠配置咱們的中間件。首先咱們來看Asp.Net Core提供的Use,Map,Run方法。

  Use方法可使管道短路(即,能夠不調用下一個中間件)。咱們再Configure方法中調用app.Use方法,若是咱們在該方法中不調用next()方法,那麼請求到達該方法就結束返回了,不會再往下一個中間件執行,即後面的Run不會執行。

 

 app.Use(async (context, next) =>
            {
                context.Response.ContentType = "text/plain;charset=utf-8;"; //解決中文亂碼
                await context.Response.WriteAsync("這是第一個Hello World");
                //await next(); //調用下一個中間件
            });

            app.Run(async (context) =>
            {
                //獲取當前進程名
                await context.Response.WriteAsync( System.Diagnostics.Process.GetCurrentProcess().ProcessName);
            });

  若是咱們放開了next(),則會繼續往下執行

  再看一下下面的代碼

            app.Use(async (context, next) =>
            {
                context.Response.ContentType = "text/plain;charset=utf-8;"; //解決中文亂碼
                await context.Response.WriteAsync("Use1以前");
                await next(); //調用下一個中間件
                await context.Response.WriteAsync("Use1以後");
            });

            app.Use(async (context, next) =>
            {
                await context.Response.WriteAsync("Use2以前");
                await next(); //調用下一個中間件
                await context.Response.WriteAsync("Use2以後");
            });
        app.Run(async (context) => { //獲取當前進程名 await context.Response.WriteAsync( System.Diagnostics.Process.GetCurrentProcess().ProcessName); });
 

  咱們能夠看到,請求過來後,以鏈式的方式執行: Use1以前 --> next --> Use2以前 --> next --> Run --> Use2以後 --> Use1以前

  Run方法是一個約定, 而且一些中間件組件可能暴露在管道末端運行的Run [Middleware]方法,若是將Run放在了Configure裏面,它也是終端中間件。

app.Run(async (context) =>
{
    context.Response.ContentType = "text/plain;charset=utf-8;"; //解決中文亂碼
    //獲取當前進程名
    await context.Response.WriteAsync("當前進程名:" + System.Diagnostics.Process.GetCurrentProcess().ProcessName);
});

  Map*擴展用做分支管道的約定。映射根據給定的請求路徑的匹配來分支請求流水線,若是請求路徑以給定路徑開始,則執行分支。

      private static void HandleMapTest1(IApplicationBuilder app)
        {
            app.Run(async context =>
            {
                await context.Response.WriteAsync("Map Test 1");
            });
        }

        private static void HandleMapTest2(IApplicationBuilder app)
        {
            app.Run(async context =>
            {
                await context.Response.WriteAsync("Map Test 2");
            });
        }

  app.Map("/map1", HandleMapTest1);

  app.Map("/map2", HandleMapTest2);

 

 

   最後咱們再來看一下Asp.Net Core提供的一些其餘的中間件。

        /*自定義默認頁(第一種方式)*/
            //DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions();
            //defaultFilesOptions.DefaultFileNames.Clear();
            //defaultFilesOptions.DefaultFileNames.Add("custom.html");  //自定義默認頁
            //app.UseDefaultFiles(defaultFilesOptions);
            /**************************************************************************/

            /*自定義默認頁(第二種方式)*/
            //FileServerOptions fileServerOptions = new FileServerOptions();
            //fileServerOptions.DefaultFilesOptions.DefaultFileNames.Clear();
            //fileServerOptions.DefaultFilesOptions.DefaultFileNames.Add("custom.html");
            //app.UseFileServer(fileServerOptions); //集合了UseStaticFiles,UseDefaultFiles,UseDirectoryBrowser
            /************************************************/

            //app.UseDefaultFiles(); //添加默認文件中間件,必須註冊在UseStaticFiles前 index.html index.htm default.html default.htm

            app.UseStaticFiles(); //添加靜態文件中間件
            //app.UseDirectoryBrowser();//暴露項目文件夾,不推薦使用

            app.UseMvcWithDefaultRoute();//在請求管道中添加帶默認路由的MVC

 

   好了,這篇博文介紹了Startup文件作了哪些事情,其中最重要的就是中間件,那麼下一篇就來聊聊Asp.Net Corez中的中間件吧。

相關文章
相關標籤/搜索