欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于.NET6?Minimal?API的使用方式詳解

 更新時(shí)間:2021年12月02日 11:07:26   作者:yi念之間  
本文我們主要是介紹了ASP.NET?Core?6?Minimal?API的常用的使用方式,在.NET6中也是默認(rèn)的項(xiàng)目方式,整體來說卻是非常的簡單、簡潔、強(qiáng)大、靈活,不得不說Minimal?API卻是在很多場(chǎng)景都非常適用的

前言

隨著.Net6的發(fā)布,微軟也改進(jìn)了對(duì)之前ASP.NET Core構(gòu)建方式,使用了新的Minimal API模式。之前默認(rèn)的方式是需要在Startup中注冊(cè)IOC和中間件相關(guān),但是在Minimal API模式下你只需要簡單的寫幾行代碼就可以構(gòu)建一個(gè)ASP.NET Core的Web應(yīng)用,真可謂非常的簡單,加之配合c#的global using和Program的頂級(jí)聲明方式,使得Minimal API變得更為簡潔,不得不說.NET團(tuán)隊(duì)在,NET上近幾年真是下了不少功夫,接下來我們就來大致介紹下這種極簡的使用模式。

使用方式

既然說它很簡單了,到底是怎么個(gè)簡單法呢。相信下載過Visual Studio 2022的同學(xué)們已經(jīng)用它新建過ASP.NET Core 6的項(xiàng)目了,默認(rèn)的方式就是Minimal API模式,這樣讓整個(gè)Web程序的結(jié)構(gòu)看起來更簡單了,加上微軟對(duì)Lambda的改進(jìn)使其可以對(duì)Lambda參數(shù)進(jìn)行Attribute標(biāo)記,有的場(chǎng)景甚至可以放棄去定義Controller類了。

幾行代碼構(gòu)建Web程序

使用Minimal API最簡單的方式就是能通過三行代碼就可以構(gòu)建一個(gè)WebApi的程序,代碼如下

var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World");
app.Run();

是的你沒有看錯(cuò),僅僅這樣運(yùn)行起來就可以,默認(rèn)監(jiān)聽的 http://localhost:5000https://localhost:5001,所以直接在瀏覽器輸入http://localhost:5000地址就可以看到瀏覽器輸出Hello World字樣。

更改監(jiān)聽地址

如果你想更改它監(jiān)聽的服務(wù)端口可以使用如下的方式進(jìn)行更改

var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World");
app.Run("http://localhost:6666");

如果想同時(shí)監(jiān)聽多個(gè)端口的話,可以使用如下的方式

var app = WebApplication.Create(args);
app.Urls.Add("http://localhost:6666");
app.Urls.Add("http://localhost:8888");
app.MapGet("/", () => "Hello World");
app.Run();

或者是直接通過環(huán)境變量的方式設(shè)置監(jiān)聽信息,設(shè)置環(huán)境變量ASPNETCORE_URLS的值為完整的監(jiān)聽URL地址,這樣的話就可以直接省略了在程序中配置相關(guān)信息了

ASPNETCORE_URLS=http://localhost:6666

如果設(shè)置多個(gè)監(jiān)聽的URL地址的話可以在多個(gè)地址之間使用分號(hào);隔開多個(gè)值

ASPNETCORE_URLS=http://localhost:6666;https://localhost:8888

如果想監(jiān)聽本機(jī)所有Ip地址則可以使用如下方式

var app = WebApplication.Create(args);
app.Urls.Add("http://*:6666");
app.Urls.Add("http://+:8888");
app.Urls.Add("http://0.0.0.0:9999");
app.MapGet("/", () => "Hello World");
app.Run();

同樣的也可以使用添加環(huán)境變量的方式添加監(jiān)聽地址

ASPNETCORE_URLS=http://*:6666;https://+:8888;http://0.0.0.0:9999

日志操作

日志操作也是比較常用的操作,在Minimal API中微軟干脆把它提出來,直接簡化了操作,如下所示

var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddJsonConsole();
var app = builder.Build();
app.Logger.LogInformation("讀取到的配置信息:{content}", builder.Configuration.GetSection("consul").Get<ConsulOption>());
app.Run();

基礎(chǔ)環(huán)境配置

無論我們?cè)谥暗?Net Core開發(fā)或者現(xiàn)在的.Net6開發(fā)都有基礎(chǔ)環(huán)境的配置,它包括 ApplicationName、ContentRootPath EnvironmentName相關(guān),不過在Minimal API中,可以通過統(tǒng)一的方式去配置

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    ApplicationName = typeof(Program).Assembly.FullName,
    ContentRootPath = Directory.GetCurrentDirectory(),
    EnvironmentName = Environments.Staging
});

Console.WriteLine($"應(yīng)用程序名稱: {builder.Environment.ApplicationName}");
Console.WriteLine($"環(huán)境變量: {builder.Environment.EnvironmentName}");
Console.WriteLine($"ContentRoot目錄: {builder.Environment.ContentRootPath}");

var app = builder.Build();

或者是通過環(huán)境變量的方式去配置,最終實(shí)現(xiàn)的效果都是一樣的

  • ASPNETCORE_ENVIRONMENT
  • ASPNETCORE_CONTENTROOT
  • ASPNETCORE_APPLICATIONNAME

主機(jī)相關(guān)設(shè)置

我們?cè)谥暗?Net Core開發(fā)模式中,程序的啟動(dòng)基本都是通過構(gòu)建主機(jī)的方式,比如之前的Web主機(jī)或者后來的泛型主機(jī),在Minimal API中同樣可以進(jìn)行這些操作,比如我們模擬一下之前泛型主機(jī)配置Web程序的方式

var builder = WebApplication.CreateBuilder(args);
builder.Host.ConfigureDefaults(args).ConfigureWebHostDefaults(webBuilder =>
{
    webBuilder.UseStartup<Startup>();
});

var app = builder.Build();

如果只是配置Web主機(jī)的話Minimal API還提供了另一種更直接的方式,如下所示

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseStartup<Startup>();
builder.WebHost.UseWebRoot("webroot");

var app = builder.Build();

默認(rèn)容器替換

很多時(shí)候我們?cè)谑褂肐OC的時(shí)候會(huì)使用其他三方的IOC框架,比如大家耳熟能詳?shù)腁utofac,我們之前也介紹過其本質(zhì)方式就是使用UseServiceProviderFactory中替換容器的注冊(cè)和服務(wù)的提供,在Minimal API中可以使用如下的方式去操作

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
//之前在Startup中配置ConfigureContainer可以使用如下方式
builder.Host.ConfigureContainer<ContainerBuilder>(builder => builder.RegisterModule(new MyApplicationModule()));

var app = builder.Build();

中間件相關(guān)

相信大家都已經(jīng)仔細(xì)看過了WebApplication.CreateBuilder(args).Build()通過這種方式構(gòu)建出來的是一個(gè)WebApplication類的實(shí)例,而WebApplication正是實(shí)現(xiàn)了 IApplicationBuilder接口。所以其本質(zhì)還是和我們之前使用Startup中的Configure方法的方式是一致的,比如我們配置一個(gè)Swagger程序?yàn)槔?/p>

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();
//判斷環(huán)境變量
if (app.Environment.IsDevelopment())
{
    //異常處理中間件
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI();
}
//啟用靜態(tài)文件
app.UseStaticFiles();

app.UseAuthorization();
app.MapControllers();

app.Run();

常用的中間件配置還是和之前是一樣的,因?yàn)楸举|(zhì)都是IApplicationBuilder的擴(kuò)展方法,我們這里簡單列舉一下

中間件名稱 描述 API
Authentication 認(rèn)證中間件 app.UseAuthentication()
Authorization 授權(quán)中間件. app.UseAuthorization()
CORS 跨域中間件. app.UseCors()
Exception Handler 全局異常處理中間件. app.UseExceptionHandler()
Forwarded Headers 代理頭信息轉(zhuǎn)發(fā)中間件. app.UseForwardedHeaders()
HTTPS Redirection Https重定向中間件. app.UseHttpsRedirection()
HTTP Strict Transport Security (HSTS) 特殊響應(yīng)頭的安全增強(qiáng)中間件. app.UseHsts()
Request Logging HTTP請(qǐng)求和響應(yīng)日志中間件. app.UseHttpLogging()
Response Caching 輸出緩存中間件. app.UseResponseCaching()
Response Compression 響應(yīng)壓縮中間件. app.UseResponseCompression()
Session Session中間件 app.UseSession()
Static Files 靜態(tài)文件中間件. app.UseStaticFiles(),?app.UseFileServer()
WebSockets WebSocket支持中間件. app.UseWebSockets()

請(qǐng)求處理

我們可以使用WebApplication中的Map{HTTPMethod}相關(guān)的擴(kuò)展方法來處理不同方式的Http請(qǐng)求,比如以下示例中處理Get、Post、Put、Delete相關(guān)的請(qǐng)求

app.MapGet("/", () => "Hello GET");
app.MapPost("/", () => "Hello POST");
app.MapPut("/", () => "Hello PUT");
app.MapDelete("/", () => "Hello DELETE");

如果想讓一個(gè)路由地址可以處理多種Http方法的請(qǐng)求可以使用MapMethods方法,如下所示

app.MapMethods("/multiple", new[] { "GET", "POST","PUT","DELETE" }, (HttpRequest req) => $"Current Http Method Is {req.Method}" );

通過上面的示例我們不僅看到了處理不同Http請(qǐng)求的方式,還可以看到Minimal Api可以根據(jù)委托的類型自行推斷如何處理請(qǐng)求,比如上面的示例,我們沒有寫Response Write相關(guān)的代碼,但是輸出的卻是委托里的內(nèi)容,因?yàn)槲覀兩厦媸纠械奈卸紳M足Func<string>的形式,所以Minimal Api自動(dòng)處理并輸出返回的信息,其實(shí)只要滿足委托類型的它都可以處理,接下來咱們來簡單一下,首先是本地函數(shù)的形式

static string LocalFunction() => "This is local function";
app.MapGet("/local-fun", LocalFunction);

還可以是類的實(shí)例方法

HelloHandler helloHandler = new HelloHandler();
app.MapGet("/instance-method", helloHandler.Hello);

class HelloHandler
{
    public string Hello()
    {
        return "Hello World";
    }
}

亦或者是類的靜態(tài)方法

app.MapGet("/static-method", HelloHandler.SayHello);

class HelloHandler
{
    public static string SayHello(string name)
    {
        return $"Hello {name}";
    }
}

其實(shí)本質(zhì)都是一樣的,那就是將他們轉(zhuǎn)換為可執(zhí)行的委托,無論什么樣的形式,能滿足委托的條件即可。

路由約束

Minimal Api還支持在對(duì)路由規(guī)則的約束,這個(gè)和我們之前使用UseEndpoints的方式類似,比如我約束路由參數(shù)只能為整型,如果不滿足的話會(huì)返回404

app.MapGet("/users/{userId:int}", (int userId) => $"user id is {userId}");
app.MapGet("/user/{name:length(20)}", (string name) => $"user name is {name}");

經(jīng)常使用的路由約束還有其他幾個(gè),也不是很多大概有如下幾種,簡單的列一下表格

限制 示例 匹配示例 說明
int {id:int} 123456789,?-123456789 匹配任何整數(shù)
bool {active:bool} true,?false 匹配?true?或?false. 忽略大小寫
datetime {dob:datetime} 2016-12-31,?2016-12-31 7:32pm 匹配滿足DateTime類型的值
decimal {price:decimal} 49.99,?-1,000.01 匹配滿足?decimal類型的值
double {height:double} 1.234,?-1,001.01e8 匹配滿足?double?類型的值
float {height:float} 1.234,?-1,001.01e8 匹配滿足?float?類型的值
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638 匹配滿足Guid類型的值
long {ticks:long} 123456789,?-123456789 匹配滿足?long?類型的值
minlength(value) {username:minlength(4)} KOBE 字符串長度必須是4個(gè)字符
maxlength(value) {filename:maxlength(8)} CURRY 字符串長度不能超過8個(gè)字符
length(length) {filename:length(12)} somefile.txt 字符串的字符長度必須是12個(gè)字符
length(min,max) {filename:length(8,16)} somefile.txt 字符串的字符長度必須介于8和l6之間
min(value) {age:min(18)} 20 整數(shù)值必須大于18
max(value) {age:max(120)} 119 整數(shù)值必須小于120
range(min,max) {age:range(18,120)} 100 整數(shù)值必須介于18和120之間
alpha {name:alpha} Rick 字符串必須由一個(gè)或多個(gè)a-z的字母字符組成,且不區(qū)分大小寫。
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 字符串必須與指定的正則表達(dá)式匹配。
required {name:required} JAMES 請(qǐng)求信息必須包含該參數(shù)

模型綁定

在我們之前使用ASP.NET Core Controller方式開發(fā)的話,模型綁定是肯定會(huì)用到的,它的作用就是簡化我們解析Http請(qǐng)求信息也是MVC框架的核心功能,它可以將請(qǐng)求信息直接映射成c#的簡單類型或者POCO上面。在Minimal Api的Map{HTTPMethod}相關(guān)方法中同樣可以進(jìn)行豐富的模型綁定操作,目前可以支持的綁定源有如下幾種

  • Route(路由參數(shù))
  • QueryString
  • Header
  • Body(比如JSON)
  • Services(即通過IServiceCollection注冊(cè)的類型)
  • 自定義綁定

綁定示例

接下來我們首先看一下綁定路由參數(shù)

app.MapGet("/sayhello/{name}", (string name) => $"Hello {name}");

還可以使用路由和querystring的混用方式

app.MapGet("/sayhello/{name}", (string name,int? age) => $"my name is {name},age {age}");

這里需要注意的是,我的age參數(shù)加了可以為空的標(biāo)識(shí),如果不加的話則必須要在url的請(qǐng)求參數(shù)中傳遞age參數(shù),否則將報(bào)錯(cuò),這個(gè)和我們之前的操作還是有區(qū)別的。

具體的類也可以進(jìn)行模型綁定,比如咱們這里定義了名為Goods的POCO進(jìn)行演示

app.MapPost("/goods",(Goods goods)=>$"商品{goods.GName}添加成功");

class Goods
{
    public int GId { get; set; }
    public string GName { get; set; }
    public decimal Price { get; set; }
}

需要注意的是HTTP方法GET、HEAD、OPTIONS、DELETE將不會(huì)從body進(jìn)行模型綁定,如果需要在Get請(qǐng)求中獲取Body信息,可以直接從HttpRequest中讀取它。

如果我們需要使用通過IServiceCollection注冊(cè)的具體實(shí)例,可以以通過模型綁定的方式進(jìn)行操作(很多人喜歡叫它方法注入,但是嚴(yán)格來說卻是是通過定義模型綁定的相關(guān)操作實(shí)現(xiàn)的),而且還簡化了具體操作,我們就不需要在具體的參數(shù)上進(jìn)行FromServicesAttribute標(biāo)記了

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<Person>(provider => new() { Id = 1, Name = "yi念之間", Sex = "Man" });
var app = builder.Build();

app.MapGet("/", (Person person) => $"Hello {person.Name}!");
app.Run();

如果是混合使用的話,也可以不用指定具體的BindSource進(jìn)行標(biāo)記了,前提是這些值的名稱在不同的綁定來源中是唯一的,這種感覺讓我想到了剛開始學(xué)習(xí)MVC4.0的時(shí)候模型綁定的隨意性,比如下面的例子

app.MapGet("/sayhello/{name}", (string name,int? age,Person person) => $"my name is {name},age {age}, sex {person.Sex}");

上面示例的模型綁定參數(shù)來源可以

參數(shù) 綁定來源
name 路由參數(shù)
age querystring
person 依賴注入

不僅僅如此,它還支持更復(fù)雜的方式,這使得模型綁定更為靈活,比如以下示例

app.MapPost("/goods",(Goods goods, Person person) =>$"{person.Name}添加商品{goods.GName}成功");

它的模型綁定的值來源可以是

參數(shù) 綁定來源
goods body里的json
person 依賴注入

當(dāng)然如果你想讓模型綁定的來源更清晰,或者就想指定具體參數(shù)的綁定來源那也是可以的,反正就是各種靈活,比如上面的示例改造一下,這樣就可以顯示聲明

app.MapPost("/goods",([FromBody]Goods goods, [FromServices]Person person) =>$"{person.Name}添加商品{goods.GName}成功");

很多時(shí)候我們可能通過定義類和方法的方式來聲明Map相關(guān)方法的執(zhí)行委托,這個(gè)時(shí)候呢依然可以進(jìn)行靈活的模型綁定,而且可能你也發(fā)現(xiàn)了,直接通過lambda表達(dá)式的方式雖然支持可空類型,但是它不支持缺省參數(shù),也就是咱們說的方法默認(rèn)參數(shù)的形式,比如

app.MapPost("/goods", GoodsHandler.AddGoods);

class GoodsHandler
{
    public static string AddGoods(Goods goods, Person person, int age = 20) => $"{person.Name}添加商品{goods.GName}成功";
}

當(dāng)然你也可以對(duì)AddGoods方法的參數(shù)進(jìn)行顯示的模型綁定處理,真的是十分的靈活

public static string AddGoods([FromBody] Goods goods, [FromServices] Person person, [FromQuery]int age = 20) => $"{person.Name}添加商品{goods.GName}成功";

在使用Map相關(guān)方法的時(shí)候,由于是在Program入口程序或者其他POCO中直接編寫相關(guān)邏輯的,因此需要用到HttpContext、HttpRequest、HttpResponse相關(guān)實(shí)例的時(shí)候沒辦法進(jìn)行直接操作,這個(gè)時(shí)候也需要通過模型綁定的方式獲取對(duì)應(yīng)實(shí)例

app.MapGet("/getcontext",(HttpContext context,HttpRequest request,HttpResponse response) => response.WriteAsync($"IP:{context.Connection.RemoteIpAddress},Request Method:{request.Method}"));

自定義綁定

Minimal Api采用了一種新的方式來自定義模型綁定,這種方式是一種基于約定的方式,無需提前注冊(cè),也無需集成什么類或者實(shí)現(xiàn)什么接口,只需要在自定義的類中存在TryParseBindAsync方法即可,這兩個(gè)方法的區(qū)別是

  • TryParse方法是對(duì)路由參數(shù)、url參數(shù)、header相關(guān)的信息進(jìn)行轉(zhuǎn)換綁定
  • BindAsync可以對(duì)任何請(qǐng)求的信息進(jìn)行轉(zhuǎn)換綁定,功能比TryParse要強(qiáng)大

接下來我們分別演示一下這兩種方式的使用方法,首先是TryParse方法

app.MapGet("/address/getarray",(Address address) => address.Addresses);

public class Address
{
    public List<string>? Addresses { get; set; }

    public static bool TryParse(string? addressStr, IFormatProvider? provider, out Address? address)
    {
        var addresses = addressStr?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        if (addresses != null && addresses.Any())
        {
            address = new Address { Addresses = addresses.ToList() };
            return true;
        }
        address = new Address();
        return false;
    }
}

這樣就可以完成簡單的轉(zhuǎn)換綁定操作,從寫法上我們可以看到,TryParse方法確實(shí)存在一定的限制,不過操作起來比較簡單,這個(gè)時(shí)候我們模擬請(qǐng)求

http://localhost:5036/address/getarray?address=山東,山西,河南,河北

請(qǐng)求完成會(huì)得到如下結(jié)果

["山東","山西","河南", "河北"]

然后我們改造一下上面的例子使用BindAsync的方式進(jìn)行結(jié)果轉(zhuǎn)換,看一下它們操作的不同

app.MapGet("/address/getarray",(Address address) => address.Addresses);

public class Address
{
    public List<string>? Addresses { get; set; }

    public static ValueTask<Address?> BindAsync(HttpContext context, ParameterInfo parameter)
    {
        string addressStr = context.Request.Query["address"];
        var addresses = addressStr?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        Address address = new();
        if (addresses != null && addresses.Any())
        {
            address.Addresses = addresses.ToList();
            return ValueTask.FromResult<Address?>(address);
        }
        return ValueTask.FromResult<Address?>(address);
    }
}

同樣請(qǐng)求http://localhost:5036/address/getarray?address=山東,山西,河南,河北 地址會(huì)得到和上面相同的結(jié)果,到底如何選擇同學(xué)們可以按需使用,得到的效果都是一樣的。如果類中同時(shí)存在TryParseBindAsync方法,那么只會(huì)執(zhí)行BindAsync方法。

輸出結(jié)果

相信通過上面的其他示例演示,我們大概看到了一些在Minimal Api中的結(jié)果輸出,總結(jié)起來其實(shí)可以分為三種情況

  • IResult 結(jié)果輸出,可以包含任何值得輸出,包含異步任務(wù)
  • Task<IResult>ValueTask<IResult>string 文本類型輸出,包含異步任務(wù)
  • Task<string>ValueTask<string>T 對(duì)象類型輸出,比如自定義的實(shí)體、匿名對(duì)象等,包含異步任務(wù) Task<T>ValueTask<T>

接下來簡單演示幾個(gè)例子來簡單看一下具體是如何操作的,首先最簡單的就是輸出文本類型

app.MapGet("/hello", () => "Hello World");

然后輸出一個(gè)對(duì)象類型,對(duì)象類型可以包含對(duì)象或集合甚至匿名對(duì)象,或者是咱們上面演示過的HttpResponse對(duì)象,這里的對(duì)象可以理解為面向?qū)ο蟮哪莻€(gè)對(duì)象,滿足Response輸出要求即可

app.MapGet("/simple", () => new { Message = "Hello World" });
//或者是
app.MapGet("/array",()=>new string[] { "Hello", "World" });
//亦或者是EF的返回結(jié)果
app.Map("/student",(SchoolContext dbContext,int classId)=>dbContext.Student.Where(i=>i.ClassId==classId));

還有一種是微軟幫我們封裝好的一種形式,即返回的是IResult類型的結(jié)果,微軟也是很貼心的為我們統(tǒng)一封裝了一個(gè)靜態(tài)的Results類,方便我們使用,簡單演示一下這種操作

//成功結(jié)果
app.MapGet("/success",()=> Results.Ok("Success"));
//失敗結(jié)果
app.MapGet("/fail", () => Results.BadRequest("fail"));
//404結(jié)果
app.MapGet("/404", () => Results.NotFound());
//根據(jù)邏輯判斷返回
app.Map("/student", (SchoolContext dbContext, int classId) => {
    var classStudents = dbContext.Student.Where(i => i.ClassId == classId);
    return classStudents.Any() ? Results.Ok(classStudents) : Results.NotFound();
});

上面我們也提到了Results類其實(shí)是微軟幫我們多封裝了一層,它里面的所有靜態(tài)方法都是返回IResult的接口實(shí)例,這個(gè)接口有許多實(shí)現(xiàn)的類,滿足不同的輸出結(jié)果,比如Results.File("foo.text")方法其本質(zhì)就是返回一個(gè)FileContentResult類型的實(shí)例

public static IResult File(byte[] fileContents,string? contentType = null,
string? fileDownloadName = null,
bool enableRangeProcessing = false,
DateTimeOffset? lastModified = null,
EntityTagHeaderValue? entityTag = null)
=> new FileContentResult(fileContents, contentType)
{
    FileDownloadName = fileDownloadName,
    EnableRangeProcessing = enableRangeProcessing,
    LastModified = lastModified,
    EntityTag = entityTag,
};

亦或者Results.Json(new { Message="Hello World" })本質(zhì)就是返回一個(gè)JsonResult類型的實(shí)例

public static IResult Json(object? data, JsonSerializerOptions? options = null, string? contentType = null, int? statusCode = null)
            => new JsonResult
            {
                Value = data,
                JsonSerializerOptions = options,
                ContentType = contentType,
                StatusCode = statusCode,
            };

當(dāng)然我們也可以自定義IResult的實(shí)例,比如我們要輸出一段html代碼。微軟很貼心的為我們提供了專門擴(kuò)展Results的擴(kuò)展類IResultExtensions基于這個(gè)類我們才能完成IResult的擴(kuò)展

static class ResultsExtensions
{
    //基于IResultExtensions寫擴(kuò)展方法
    public static IResult Html(this IResultExtensions resultExtensions, string html)
    {
        ArgumentNullException.ThrowIfNull(resultExtensions, nameof(resultExtensions));
        //自定義的HtmlResult是IResult的實(shí)現(xiàn)類
        return new HtmlResult(html);
    }
}

class HtmlResult:IResult
{
    //用于接收html字符串
    private readonly string _html;

    public HtmlResult(string html)
    {
        _html = html;
    }

    /// <summary>
    /// 在該方法寫自己的輸出邏輯即可
    /// </summary>
    /// <returns></returns>
    public Task ExecuteAsync(HttpContext httpContext)
    {
        httpContext.Response.ContentType = MediaTypeNames.Text.Html;
        httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(_html);
        return httpContext.Response.WriteAsync(_html);
    }
}

定義完成這些我們就可以直接在Results類中使用我們定義的擴(kuò)展方法了,使用方式如下

app.MapGet("/hello/{name}", (string name) => Results.Extensions.Html(@$"<html>
    <head><title>Index</title></head>
    <body>
        <h1>Hello {name}</h1>
    </body>
</html>"));

這里需要注意的是,我們自定義的擴(kuò)展方法一定是基于IResultExtensions擴(kuò)展的,然后再使用的時(shí)候注意是使用的Results.Extensions這個(gè)屬性,因?yàn)檫@個(gè)屬性是IResultExtensions類型的,然后就是我們自己擴(kuò)展的Results.Extensions.Html方法。

總結(jié)

本文我們主要是介紹了ASP.NET Core 6 Minimal API的常用的使用方式,相信大家對(duì)此也有了一定的了解,在.NET6中也是默認(rèn)的項(xiàng)目方式,整體來說卻是非常的簡單、簡潔、強(qiáng)大、靈活,不得不說Minimal API卻是在很多場(chǎng)景都非常適用的。當(dāng)然我也在其它地方看到過關(guān)于它的評(píng)價(jià),褒貶不一吧,筆者認(rèn)為,沒有任何一種技術(shù)是銀彈,存在即合理。如果你的項(xiàng)目夠規(guī)范夠合理,那么使用Minimal API絕對(duì)夠用,如果不想用或者用不了也沒關(guān)系,能實(shí)現(xiàn)你想要結(jié)果就好了,其實(shí)也沒啥好評(píng)價(jià)的。

到此這篇關(guān)于簡單聊下.NET6?Minimal?API的使用方式的文章就介紹到這了,更多相關(guān).NET6?Minimal?API內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論