dotnet6 Hangfire範例

目的 在windows系統上想執行排程有兩個選擇 使用windows工作排程器執行exe檔 透過Hangfire進行排程管理 此次教學說明如何使用Hangfire執行排程 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Hangfire Hangfire.InMemory 編輯Program.cs檔 using Hangfire; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //註冊hangfire並且使用記憶體保存排程, //預設所下載的HangFire套件可以使用sqlserver,可透過config.UseSqlServerStorage();,但需要設定 builder.Services.AddHangfire(config => { config.UseInMemoryStorage(); }); //註冊hangfire要使用的伺服器,伺服器就是上面所寫的使用記憶體當伺服器 builder.Services.AddHangfireServer(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); //使用hangfire內建的儀表板 app.UseHangfireDashboard(); app.MapControllers(); app.Run(); ...

October 11, 2022

dotnet6 HttpClient單元測試範例

目的 面試的時候被問到要如何做包含外部api的單元測試問題,稍微查一下其實很簡單,怎麼當下答不出來呢? 主要有兩種方式,一種為.net core 2.1以後有提供IHttpClientFactory的介面可以使用。 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 建立資料夾 編輯Program.cs檔案 註冊AddHttpClient。 builder.Services.AddHttpClient(); 新增一個類別檔 加入前 加入後 建構子注入 將註冊的httpclient透過建構子注入 readonly IHttpClientFactory _httpClientFactory; public CallAPIServices(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } 加入前 加入後 新增方法 新增一個會去發外部請求的方法,模擬當有包含第三方api時如何測試 public async Task<string> Get() { var client = _httpClientFactory.CreateClient(); var response = await client.GetAsync("https://example.com"); if (response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); return responseString; } return ""; } 新增測試專案 對方案點選右鍵>加入>新增專案 ...

October 10, 2022

dotnet6 Moq範例

目的 進行單元測試時,可以隔絕依賴的項目。 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 建立新的類別庫 進行命名時通常會與要測試的專案同名並加上結尾.Tests,以此範例就會變成MoqExample.Tests NuGet加入套件 針對xUnitExample.Tests加入相關套件 xunit xunit.runner.visualstudio Microsoft.NET.Test.Sdk coverlet.collector Moq 針對MoqExample.Tests類別庫加入參考 引用要測試的專案,才能將測試與實際專案切分開來 新增WeatherForecastControllerTests.cs類別檔 刪除預設的類別檔(Class1.cs),並在MoqExample.Tests專案新增對應資料夾,與類別檔並加結尾Tests。 編輯WeatherForecastControllerTests.cs類別檔 測試都會分三個階段 Arrange:準備階段,包含初始化相關資料 Act:執行測試方法後所取得的結果 Assert:驗證Act取得的結果是否符合預期結果 這次要測試的是controller,有注入Ilogger,如何將Ilogger隔開的關鍵就是使用Moq這個套件 using Microsoft.Extensions.Logging; using Moq; using MoqExample.Controllers; using Xunit; namespace MoqExample.Tests.Controllers { public class WeatherForecastControllerTests { [Fact] public void Get() { //Arrange //透過mock將外界的介面包起來 var MockLogger = new Mock<ILogger<WeatherForecastController>>(); //當成物件傳入controller,代替實際的介面 var Controllers = new WeatherForecastController(MockLogger.Object); //Act //執行要測試的函式 var Results = Controllers.Get(); //Assert //確認結果不為null Assert.NotNull(Results); //確認結果數量等於5 Assert.Equal(5, Results.Count()); } } } ...

October 9, 2022

dotnet6 NLog進階範例

目的 在寫nlog.config檔案時覺得怎麼有點複雜,我只是需要簡單的設定檔就好了,最後決定透過appsetting來做設定 將log文件採用非同步寫入,可大幅提升效能 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 4.NuGet加入套件 NLog NLog.Web.AspNetCore 編輯Program.cs檔 using NLog; using NLog.Web; //初始化NLog var logger = LogManager.Setup() //載入Configuration並且讀取appsetting來使用 .LoadConfigurationFromAppSettings() .GetCurrentClassLogger(); try { logger.Debug("init main"); var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Logging.ClearProviders(); builder.Host.UseNLog(); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //以下省略 編輯appsetting.json 設定NLog,包含 throwConfigExceptions:設定檔錯誤時會跳exception 使用非同步方式寫入檔案 targets:設定輸出的格式,例如txt檔案或是Console顯示 rules:什麼情況要做什麼動作,例如log名稱為Microsoft.AspNetCore最小等級是warn時寫到Console ILogger NLog Level 0 Trace Trace Level 1 Debug Debug Level 2 Information Info Level 3 Warning Warn Level 4 Error Error Level 5 Critical Fatal Level 6 None NLog沒有 { "NLog": { "throwConfigExceptions": true, "targets": { "async": true, "logfile": { "type": "File", "fileName": "c:/temp/nlog-${shortdate}.txt" }, "logconsole": { "type": "Console" } }, "rules": [ { "logger": "Microsoft.AspNetCore", "minLevel": "Warn", "writeTo": "logconsole" }, { "logger": "*", "minLevel": "Info", "writeTo": "logfile" } ] } } ...

October 8, 2022

dotnet6 xUnit範例

目的 單元測試 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 建立新的類別庫 進行命名時通常會與要測試的專案同名並加上結尾.Tests,以此範例就會變成xUnitExample.Tests NuGet加入套件 針對xUnitExample.Tests加入相關套件 xunit xunit.runner.visualstudio Microsoft.NET.Test.Sdk coverlet.collector 新增Calculator.cs類別檔 在xUnitExample專案新增Calculator.cs類別檔 新增一個簡單的加法函式 public static class Calculator { public static double Add(int a, int b) { return a + b; } } 針對xUnitExample.Tests類別庫加入參考 引用要測試的專案,才能將測試與實際專案切分開來 新增CalculatorTests.cs類別檔 刪除預設的類別檔(Class1.cs),建立對應的資料夾以及類別檔案,並在結尾加上Tests 編輯CalculatorTests.cs類別檔 測試都會分三個階段 Arrange:準備階段,包含初始化相關資料 Act:執行測試方法後所取得的結果 Assert:驗證Act取得的結果是否符合預期結果 public class CalculatorTests { //告訴編譯器要執行的測試方法 [Fact] public void Add_() { //Arrange double Expected = 20; //Act var Actual = Calculator.Add(5, 15); //Assert Assert.Equal(Expected, Actual); } } ...

October 8, 2022

dotnet6 NLog範例

目的 在webapi專案下使用NLog套件 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 NLog NLog.Web.AspNetCore 新增nlog.config檔案 在根目錄新增nlog.config檔案 nlog.config寫入程式 在nlog.config寫入官方範例 <?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="Info" internalLogFile="c:\temp\internal-nlog-AspNetCore.txt"> <!-- enable asp.net core layout renderers --> <extensions> <add assembly="NLog.Web.AspNetCore"/> </extensions> <!-- the targets to write to --> <targets> <!-- File Target for all log messages with basic details --> <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-AspNetCore-all-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" /> <!-- File Target for own log messages with extra web details using some ASP.NET core renderers --> <target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-AspNetCore-own-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" /> <!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection --> <target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" /> </targets> <!-- rules to map from logger name to target --> <rules> <!--All logs, including from Microsoft--> <logger name="*" minlevel="Trace" writeTo="allfile" /> <!--Output hosting lifetime messages to console target for faster startup detection --> <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="lifetimeConsole, ownFile-web" final="true" /> <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) --> <logger name="Microsoft.*" maxlevel="Info" final="true" /> <logger name="System.Net.Http.*" maxlevel="Info" final="true" /> <logger name="*" minlevel="Trace" writeTo="ownFile-web" /> </rules> </nlog> 只擷取部分畫面 ...

October 8, 2022

dotnet6 Serilog進階範例

目的 讀取appsetting設定檔 二階段初始化 為了簡單化故將Log存入SQLite 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Serilog.AspNetCore Serilog.Sinks.SQLite 編輯Program.cs檔 using Serilog; //第一階段初始化 // var builder = WebApplication.CreateBuilder(args);未使用二階段參數化,builder會跑到try外面 Log.Logger = new LoggerConfiguration() //.ReadFrom.Configuration(builder.Configuration) .CreateBootstrapLogger(); try { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //第二階段初始化可以取得appsetting的內容,如不使用第二階段初始化, //會需要將 var builder宣告式會移出try(如上方註解處),就會有風險未捕獲builder的錯誤 builder.Host.UseSerilog( (hostingContext, services, loggerConfiguration) => { //使用appsetting loggerConfiguration.ReadFrom.Configuration(builder.Configuration); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); //紀錄每個Request的資料,須注意要放在讀取靜態檔案(app.UseStaticFiles())後面,因為靜態檔案的狀態通常不需要紀錄資訊 app.UseSerilogRequestLogging(); //以下省略 ...

October 7, 2022

dotnet6 Serilog範例

目的 在webapi專案下使用serilog套件 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Serilog.AspNetCore 編輯Program.cs檔 在最外層包一個try catch目的是為了捕捉啟動階段的錯誤 using Serilog; using Serilog.Events; Log.Logger = new LoggerConfiguration() //Serilog要寫入的最低等級為Information .MinimumLevel.Information() //Microsoft.AspNetCore開頭的類別等極為warning .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) //寫log到Logs資料夾的log.txt檔案中,並且以天為單位做檔案分割 .WriteTo.File("./Logs/log.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); try { Log.Information("Starting web host"); var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //controller可以使用ILogger介面來寫入log紀錄 builder.Host.UseSerilog(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); return 0; } catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly"); return 1; } finally { Log.CloseAndFlush(); } ...

October 7, 2022

dotnet6 EFCore語法說明

目的 說明EFCore基本語法,EFCore的基礎為Linq,所以使用上與Linq邏輯一模一樣,只是語法有些微差異。 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Microsoft.EntityFrameworkCore.Sqlite Microsoft.EntityFrameworkCore.Design 新增Student.cs類別檔 新增Models資料夾,並在裡面新增Student.cs類別檔 編輯Student.cs類別檔 public class Student { public int Id { get; set; } public string Name { get; set; } = "BillHuang"; public int Age { get; set; } } 新增EFCoreContext.cs類別檔 新增DBContext資料夾,並在裡面新增EFCoreContext.cs類別檔 編輯EFCoreContext.cs類別檔 //別忘了using using Microsoft.EntityFrameworkCore; using EFCoreExample_Advanced.Models; namespace EFCoreExample_Advanced.DBContext { //繼承DbContext public class EFCoreContext : DbContext { //複寫OnConfiguring protected override void OnConfiguring(DbContextOptionsBuilder options) { //指定連線字串,連到SQLite options.UseSqlite("Data Source=Student.sqlite"); } //設定student資料表 public DbSet<Student> Students { get; set; } } } ...

October 5, 2022

dotnet6 EFCore範例

目的 透過EFCore對db做查詢,為了降低門檻採用SQLite當範例資料庫。 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Microsoft.EntityFrameworkCore.Sqlite Microsoft.EntityFrameworkCore.Design 新增Student.cs類別檔 新增Models資料夾,並在裡面新增Student.cs類別檔 編輯Student.cs類別檔 public class Student { public int Id { get; set; } public string Name { get; set; } = "BillHuang"; public int Age { get; set; } } 新增EFCoreContext.cs類別檔 新增DBContext資料夾,並在裡面新增EFCoreContext.cs類別檔 編輯EFCoreContext.cs類別檔 //別忘了using using Microsoft.EntityFrameworkCore; using EFCoreExample.Models; namespace EFCoreExample.DBContext { //繼承DbContext public class EFCoreContext : DbContext { //複寫OnConfiguring protected override void OnConfiguring(DbContextOptionsBuilder options) { //指定連線字串,連到SQLite options.UseSqlite("Data Source=Student.sqlite"); } //設定student資料表 public DbSet<Student> Students { get; set; } } } ...

October 4, 2022