從明面上學習ASP.NET Core


一、前言

    這篇文章就是從能看到地方去學習Core,沒有很深奧,也沒有很難懂,現在我們開始吧。

二、構建項目,引發思考

    創建項目的步驟真的很簡單,你要是不會,我真也沒法了,我這是創建的MVC的項目。

    

    

    接下來我們開始找不同,這個小學生也會的東西,我相信也難不到大家,這里我們主要說重點的不同:

    1. 少了Content和Scripts文件夾,多了wwwroot;

    2.少了配置文件web.config,多了appsettings.json;

    3.少了App_Start文件夾,多了Program.cs和Startup.cs;

   后面確實,實現了前面的功能,接下來引發下我們的思考,帶着這些問題我們來學習Core:

    配置文件:

    1.為什么appsettings.json能默認成為配置文件?

    2.怎么讀取配置文件?

    3.Global.asax如何在core中體現;

   DI:

   1.為什么全部能按照接口的方式進行注入?

   2.怎么替換掉內置的DI?

   MVC:

   1.Core的請求和MVC的請求有什么不同?

   2.Core的認證和授權怎么處理?

   懷着這些問題我們來簡單結合源碼分析下,另外最后我們在上傳一個簡單的增刪改查項目完成我們項目結束。

三、配置文件

   GitHub地址:https://github.com/aspnet/MetaPackages/tree/dev/src/Microsoft.AspNetCore

   1.為什么appsettings.json能默認成為配置文件?

   這個問題看下主要部分在這個地址下面:https://github.com/aspnet/MetaPackages/blob/dev/src/Microsoft.AspNetCore/WebHost.cs,我截取下主要代碼;

      public static IWebHostBuilder CreateDefaultBuilder(string[] args)
        {
            var builder = new WebHostBuilder();

            if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey)))
            {
                builder.UseContentRoot(Directory.GetCurrentDirectory());
            }
            if (args != null)
            {
                builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
            }

            builder.UseKestrel((builderContext, options) =>
                {
                    options.Configure(builderContext.Configuration.GetSection("Kestrel"));
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    var env = hostingContext.HostingEnvironment;

                    config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                          .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

                    if (env.IsDevelopment())
                    {
                        var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                        if (appAssembly != null)
                        {
                            config.AddUserSecrets(appAssembly, optional: true);
                        }
                    }

                    config.AddEnvironmentVariables();

                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                .ConfigureLogging((hostingContext, logging) =>
                {
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                    logging.AddDebug();
                })
                .ConfigureServices((hostingContext, services) =>
                {
                    // Fallback
                    services.PostConfigure<HostFilteringOptions>(options =>
                    {
                        if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
                        {
                            // "AllowedHosts": "localhost;127.0.0.1;[::1]"
                            var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                            // Fall back to "*" to disable.
                            options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
                        }
                    });
                    // Change notification
                    services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
                        new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));

                    services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
                })
                .UseIISIntegration()
                .UseDefaultServiceProvider((context, options) =>
                {
                    options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
                });

            return builder;
        }
View Code

   2.怎么讀取配置文件?

   我主要提供了2種方式,這里前提是引入Microsoft.AspNetCore.All這個dll,這個里面很多我們需要的東西

   從appsettings.json增加配置讀取,有兩種一個是更改配置以后立即生效,一種是重啟以后才生效,具體看下代碼:

  //配置如下
  "JwtSettings": {
    "Issuer": "http://localhost:52588",
    "Audience": "http://localhost:52588",
    "SecretKey": "1235455llllll"
  },
  "UserSetting": {
    "Name": "wtzzzzz",
    "Age": 12
  }
  //讀取配置
          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_1);


            //讀取JWT配置文件
            services.Configure<JwtSettingsModel>(Configuration.GetSection("JwtSettings"));
            //讀取User配置文件
            services.Configure<UserSettingModel>(Configuration.GetSection("UserSetting"));
        }
       //controller讀取
              //不支持實時更新
        private readonly IOptions<JwtSettingsModel> _jwtConfiguration;
        //支持實時更新
        private readonly IOptionsSnapshot<UserSettingModel> _userConfiguration;
        public HomeController(IOptions<JwtSettingsModel> jwtConfiguration,IOptionsSnapshot<UserSettingModel> userConfiguration)
        {
            _jwtConfiguration = jwtConfiguration;
            _userConfiguration = userConfiguration;
        }
        public IActionResult Index()
        {
            ViewBag.Issuer = _jwtConfiguration.Value.Issuer;
            ViewBag.Name = _userConfiguration.Value.Name;
            ViewBag.PersonName =AppConfigurtaionHelper.GetAppSettings<PersonAppSettingModel>("PersonSetting").Area;
            return View();
        }
View Code

  從外部引入配置文件,這個時候我們要做一件事情,將你新建的配置文件的屬性設置為始終復制,至於這個原理是啥我不懂,有大神可以指點下,剩下的具體看代碼吧;

{
  "PersonSetting": {
    "Area": "China"
  }
}

//外部的工具類
    public class AppConfigurtaionHelper
    {
        public static T GetAppSettings<T>(string key) where T : class, new()
        {
            IConfiguration config = new ConfigurationBuilder()
            .Add(new JsonConfigurationSource { Path = "/Config/setting.json", ReloadOnChange = true })
            .Build();



            var appconfig = new ServiceCollection()
            .AddOptions()
            .Configure<T>(config.GetSection(key))
            .BuildServiceProvider()
            .GetService<IOptions<T>>()
            .Value;



            return appconfig;
        }
    }
View Code

  3.Global.asax如何在core中體現;

        public void Configure(IApplicationBuilder app, IHostingEnvironment env,IApplicationLifetime application)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            //類似於Application
            //開始
            application.ApplicationStarted.Register(() =>
            {
                Console.WriteLine("開始了注意");
            });

            //運行中
            application.ApplicationStopping.Register(() =>
            {
                Console.WriteLine("運行中");
            });

            //結束
            application.ApplicationStopped.Register(() =>
            {
                Console.WriteLine("結束了休息下");
            });

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

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

  IApplicationLifetime這個實現替代在傳統應用中Application中生命周期的位置,這個我在上面的代碼中已有體現,使用命令的方式運行在控制台就可以看到;

四、DI

 針對這個問題,我只能這么說為了為了提高大家,給大家實現一個容器,讓大家玩的開心一下,讓DI和IOC的思想深入內心,這點有點類似Java操作了,其實早就該這樣了,已經讓我們變大太懶了,哈哈,借用下蔣神的話,ASP.NET Core的核心是通過一個Server和若干注冊的Middleware構成的管道,不論是管道自身的構建,還是ServerMiddleware自身的實現,以及構建在這個管道的應用,都需要相應的服務提供支持,ASP.NET Core自身提供了一個DI容器來實現針對服務的注冊和消費。換句話說,不只是ASP.NET Core底層框架使用的服務是由這個DI容器來注冊和提供,應用級別的服務的注冊和提供也需要以來這個DI容器,所以正如本文標題所說的——學習ASP.NET Core,你必須了解無處不在的依賴注入

 附上大神的地址:https://www.cnblogs.com/artech/p/dependency-injection-in-asp-net-core.html

 不懂DIIOC的我也附上騰飛大神的地址:https://www.cnblogs.com/jesse2013/p/di-in-aspnetcore.html,

 騰飛大神博客里面已經將我想要的說2個問題說的很明白了,我這里還是在稍稍說一下吧。

 生命周期問題:

   Transient: 每一次GetService都會創建一個新的實例

   Scoped每次Http請求只會產生一個實例;

   Singleton整個應用程序生命周期以內只創建一個實例 

   這個大神博客里面也有介紹,官方也有介紹,大家可以看下https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1

   容器的替換:

public IServiceProvider ConfigureServices(
  IServiceCollection services){
    services.AddMvc();
    // Add other framework services
 
    // Add Autofac
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterModule<DefaultModule>();
    containerBuilder.Populate(services);
    var container = containerBuilder.Build();
    return new AutofacServiceProvider(container);
}
View Code

五、MVC

   1.Core的請求和MVC的請求有什么不同?

   看圖說話,主要設計不同主要體現在蔣神說的那句話,Core按照中間件的形式設計,最后全部注入到DI,這個時候我們考慮一個問題,我們想替換任何一個都將變得很容易,但是同樣我們又會衍生另外一個問題,當我們服務之間存在依賴的時候,就需要按照順序進行注入,這個問題需要重視一下,當然微軟在設計上也考慮到這點,這里也是簡單寫個小demo,當你訪問網站的時候就會發現網站按照順序輸出來了。MVC還是在IHttpMoudle和IHttpHandle上面做擴展或解耦,整體上本質是不變得,對這塊不了解的可以推薦幾篇博客給大家看看;推薦大龍龍MVC系列:http://www.cnblogs.com/edisonchou/p/3911558.html

    

    

            //注冊中間件
            app.Use(async (context,next)=>
            {
                await context.Response.WriteAsync("1");
                await next.Invoke();
            });

            app.Use(next =>
            {
                return (context) =>
                {
                    context.Response.WriteAsync("2");
                    return next(context);
                };
            });

            app.Run(async (context) => 
            {
                await context.Response.WriteAsync("3");
            });
View Code

 六、結束

    下一篇我們再說,Demo還沒時間做好,另外強烈推薦大家去看官方文檔:https://docs.microsoft.com/zh-cn/aspnet/core/migration/http-modules?view=aspnetcore-2.1,真的比什么都管用!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM