NET Core-學習筆記(二)

神牛003發表於2016-07-13

這裡要分享的是接著上篇:NET Core-學習筆記(一)展開的繼續學習core筆記,有不妥之處或者更好見解的地方希望各位朋友多多分享。

下面是本篇將要分享的學習步奏,對於剛學或者即將要學習的朋友做個相互交流:

1.一起閱覽core框架自動生成的Controller程式碼

2.路由及路由引數格式限制

3.兩種方法設定虛擬路徑訪問資原始檔夾和效果區別

4.怎麼設定異常訪問時全域性返回資訊

5.構造器依賴注入方式ILogger,IOptions例子

6.ConfigurationBuilder使用

 

下面一步一個腳印的來分享:

1.一起閱覽core框架自動生成的Controller程式碼

首先,咋們來看一個圖

重點部分已經使用紅色框好了,先是這個ApplicationDbContext應用程式資料上下文,是由構造器傳遞進來的,但是這種情況一般是需要new 這個構造器對應的class,才能傳遞進入引數,當翻遍整個專案都暫時沒有找到對應new這個Controller的地方,因此這也延伸出了這裡要說的注入方式;這個ApplicationDbContext大家可以開啟專案檔案Startup.cs裡面有這樣一段:

1 services.AddDbContext<ApplicationDbContext>(options=>options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
View Code

是的剛才說的訪問資料庫上下文就是由這裡注入進來的,只需要這麼一段,就能連結上資料庫了,當讓裡面的Configuration.GetConnectionString是獲取資料庫字串,這些上一篇文章簡單介紹了下;

其次,大家可以看到Controller裡面的幾個操作方法都是async Task的模式,對應的方法內使用的也是await FunAsync();來返回資料,這裡的幾個關鍵字大家應該很熟悉了是4.5框架擴充套件出來的;簡單說下本人使用這幾個關鍵詞一般注意的邏輯,async await兩個肯定是成對出現的,await從單詞也能看出是等待的意思,主要是等待後面的方法執行完成返回結果,返回的結果對應的值應該是Task包裝的資料,而Task任務都是有Result,這樣通過Result獲取之前方法執行的結果;

2.路由及路由引數格式限制

首先,說道mvc就不得不說對應的路由core框架設定路由是在StartUp.cs檔案Configure方法中,初始化程式碼如下:

1 //設定mvc路由
2             app.UseMvc(routes =>
3             {
4                 //這裡的{id?} ?號表示可以有可無
5                 routes.MapRoute(
6                     name: "default",
7                     template: "{controller=Home}/{action=Index}/{id?}");
8             });
View Code

這裡有兩種設定預設值的方式一種就是上面程式碼那樣直接=號後面設定預設值,另外一種就是MapRoute方法的第三個引數和以前mvc版本一樣new{param}的格式,大家可以自己試試;

然後,我們一起引數格式限制,直接在引數後面:資料型別(如 id:int),這個時候引數只能傳遞對應的資料型別的資料,這裡列舉兩個格式如圖(注如果是正則無需可以去掉\):

1  routes.MapRoute(
2                   name: "first",
3                   template: "{controller=Home}/{action=Index}/{id:int}");
4                 routes.MapRoute(
5                   name: "second",
6                   template: "{controller=Home}/{action=Index}/{id:regex(d+)}");
View Code

很實用更多的限制可以檢視:https://docs.asp.net/en/latest/fundamentals/routing.html

3.兩種方法設定虛擬路徑訪問資原始檔夾和效果區別

首先,咋們定位到Startup.cs檔案Configure方法,要開放檢視可訪問資源的目錄需要用到UseDirectoryBrowser和UseFileServer兩個方法,其實他們都對應ConfigureServices服務方法中新增的AddDirectoryBrowser()服務,所以需要現在ConfigureServices服務方法中增加一段services.AddDirectoryBrowser();程式碼;

先來看UseDirectoryBrowser方法,我們一起在core專案跟目錄下建立一個angularjs資料夾並在裡面增加angular-1.0.js檔案,檔案內容可以隨意(我這裡只有一段註釋///這裡是ng),目錄結果如圖:

然後在Configure方法增加如下程式碼:

 1  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 2         {
 3 
 4             //啟動磁碟檢視
 5             app.UseDirectoryBrowser(new DirectoryBrowserOptions
 6             {
 7                 FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "angularjs")),
 8                 RequestPath = "/ng"
 9 
10             });
11         }
View Code

FileProvider對應的PhysicalFileProvider主要用來設定物理路徑,RequestPath對應的是虛擬路徑也就是開放給瀏覽器可訪問資源的路徑,來看下執行dotnet run命令後瀏覽器效果:

這裡效果是可以點選js檔案,但是無法直接在瀏覽器中展示js檔案的內容,也就是無法訪問到js檔案;

再來看UseFileServer(),我們把剛才的UseDirectoryBrowser程式碼先註釋避免影響效果,然後在Configure方法中增加如下程式碼:

 1  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 2         {
 3             app.UseFileServer(new FileServerOptions()
 4             {
 5                 FileProvider = new PhysicalFileProvider(
 6                 Path.Combine(Directory.GetCurrentDirectory(), "angularjs")),
 7                 RequestPath = "/ng1",
 8                 EnableDirectoryBrowsing = true
 9             });
10         }
View Code

注意這裡的虛擬路徑設定的名稱是ng1,並且增加了一段EnableDirectoryBrowsing=true這句話的意思是允許磁碟瀏覽效果相當於前面增加的程式碼services.AddDirectoryBrowser()只是這裡不需要這句也能瀏覽檔案目錄,看效果:

這裡也能瀏覽目錄結構了,然後點選js檔案能在瀏覽器中看到:

是的這就是js檔案的內容,這種方式直接就能下載某個檔案,而前面第一種就不行;如果希望第一種也能下載或者檢視js檔案,那麼可以使用UseStaticFiles()方法來設定,程式碼如下:

 1 app.UseStaticFiles(new StaticFileOptions
 2             {
 3 
 4                 FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "angularjs")), //物理根路徑
 5                 RequestPath = "/ng"  //設定訪問虛擬路徑
 6 
 7             });
 8 
 9             //啟動磁碟檔案檢視
10             app.UseDirectoryBrowser(new DirectoryBrowserOptions
11             {
12                 FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "angularjs")),
13                 RequestPath = "/ng"
14 
15             });
View Code

注意兩個方法對應的引數RequestPath都是"/ng",這裡目的就是吧這種兩個虛擬路徑設定成一樣的,UseStaticFiles()方法功能是執行某個目錄下檔案被訪問,而預設.netcore自動生成的程式碼中有app.UseStaticFiles();這麼一句,效果是預設只允許訪問專案wwwroot資料夾中的靜態資源,要訪問其他根目錄下的靜態資源可以設定成上面的程式碼就行了,需要注意的是自定義的訪問資源設定必須要在預設程式碼app.UseStaticFiles();下面才行,不然無法使用自帶的靜態檔案。

 4.怎麼設定異常訪問時全域性返回資訊

這裡要介紹的方法同樣在Configure方法中執行,UseStatusCodePages()和UseExceptionHandler()函式,目前只實驗了UseStatusCodePages一種引數設定,其他過載的沒有試,希望朋友們測試過後能告知下效果和應用場景,謝謝;

先看,app.UseStatusCodePages("text/plain", "這是 response返回的status code: {0}");我這裡直接返回的是文字資料到頁面上,效果是在瀏覽器中輸入了一個不在路由中的地址,那麼瀏覽器就會顯示此資訊,這裡面要注意的是{0},大家可以看下方法的備註說明,說明的意思大致是這裡直接使用佔位符表示Response返回的Status code程式碼,假如我這裡訪問一個不再路由中的地址效果如下:

然後,app.UseExceptionHandler("/Home/Error");這個是建立專案預設的程式碼,這裡指向的路由是HomeController中的Error方法,對應的試圖我沒有找到,不知道是專案故意不需要還是怎麼樣子,有知道的朋友告知下;

5.構造器依賴注入方式例子

構造器依賴注入其實前面有講過,就是ApplicationDbContext和第一篇分享的程式碼中,這裡說的是另外兩個netcore專案自帶的東西ILogger<T>(日誌服務)和IOptions<T>(選項訪問服務),直接上程式碼:

 1  public class ArticlesController : Controller
 2     {
 3         private readonly ApplicationDbContext _context;
 4 
 5         private readonly IOptions<Article> _opArticle;
 6 
 7         private readonly ILogger<ArticlesController> _log;
 8 
 9 
10         public ArticlesController(ApplicationDbContext context, IOptions<Article> opArticle, ILogger<ArticlesController> log)
11         {
12             _context = context;
13             _opArticle = opArticle;
14             _log = log;
15         }
16 
17         // GET: Articles
18         public async Task<IActionResult> Index()
19         {
20             _log.LogInformation("I {0} {1}", "love", "zuguo");
21             ViewBag.TResult = 4 + 5;
22             ViewBag.TouTiao = _opArticle.Value.Title;
23 
24             return View(await _context.Article.ToListAsync());
25         }
26     }
View Code

這裡的ILogger<T>通過構造器賦值給了只讀變數_log,因為是依賴注入進來的,所以可以直接使用方法我這裡用到的是LogInformation方法其中一個過載,效果是在訪問這個Controller的Index時候cmd命令窗顯示了這個Info等級的資訊:

更多的等級資訊請檢視:https://docs.asp.net/en/latest/fundamentals/logging.html

相對而言IOptions<T>使用的時候需要手動在Startup.cs檔案中ConfigureServices方法設定程式碼services.AddOptions()來新增服務,這個選項訪問服務功能可以把滿足它泛型需求的class,new()的類注入到其他的地方,這裡有一個例子在ConfigureServices方法中新增如下程式碼:

1 services.AddOptions();
2             //初始化引數資訊
3             services.Configure<Models.AiticleModels.Article>(b =>
4             {
5 
6                 b.Title = "今日頭條,愛國活動";
7             });
View Code

然後可以在通過構造器注入的某個地方獲取引數值,只需要被注入物件.Value這就能獲取到注入進來的泛型T例項,對應的程式碼就是第5點開始的程式碼,效果:

 

6.ConfigurationBuilder使用

先發一段框架自動生成的程式碼:

 1 public Startup(IHostingEnvironment env)
 2         {
 3             //這裡建立ConfigurationBuilder,其作用就是載入Congfig等配置檔案
 4             var builder = new ConfigurationBuilder()
 5 
 6                 //env.ContentRootPath:獲取當前專案的跟路徑
 7                 .SetBasePath(env.ContentRootPath)
 8                 //使用AddJsonFile方法把專案中的appsettings.json配置檔案載入進來,後面的reloadOnChange顧名思義就是檔案如果改動就重新載入
 9                 .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
10                 //這裡關注的是$"{param}"的這種寫法,有點類似於string.Format()
11                 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
12 
13             if (env.IsDevelopment())
14             {
15                 //待研究
16                 builder.AddUserSecrets();
17 
18                 //待研究
19                 builder.AddApplicationInsightsSettings(developerMode: true);
20             }
21 
22             builder.AddEnvironmentVariables();
23 
24             //這返回一個配置檔案跟節點:IConfigurationRoot
25             Configuration = builder.Build();
26            
27         }
View Code

這個ConfigurationBuilder在啟動器Startup中載入的時候就去讀取配置檔案(更多資訊可以看第一篇或程式碼註釋);這裡我們使用AddInMemoryCollection方法增加配置檔案例項的資料:

//增加配置資料
            builder.AddInMemoryCollection(new Dictionary<string, string> {
                { "home","zuguo"}
            });
View Code

在後就以在Configuration使用的地方獲取到這是的值,這裡使用的是

var home = Configuration["home"];
Console.WriteLine($"hello,{home}");

在命令窗顯示的資訊如:

 

這篇就到這裡,希望給大家帶來了好處,希望更多的心得篇,勿噴。

 

相關文章