溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

.NET6?Minimal?API的使用方式是什么

發(fā)布時(shí)間:2021-12-02 14:08:28 來(lái)源:億速云 閱讀:129 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹“.NET6 Minimal API的使用方式是什么”,在日常操作中,相信很多人在.NET6 Minimal API的使用方式是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”.NET6 Minimal API的使用方式是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

使用方式

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

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

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

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

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

更改監(jiān)聽(tīng)地址

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

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

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

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

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

ASPNETCORE_URLS=http://localhost:6666

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

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

如果想監(jiān)聽(tīng)本機(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)聽(tīng)地址

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

日志操作

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

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)境配置

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

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

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

var app = builder.Build();

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

  • ASPNETCORE_ENVIRONMENT

  • ASPNETCORE_CONTENTROOT

  • ASPNETCORE_APPLICATIONNAME

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

我們?cè)谥暗?Net Core開(kāi)發(fā)模式中,程序的啟動(dòng)基本都是通過(guò)構(gòu)建主機(jī)的方式,比如之前的Web主機(jī)或者后來(lái)的泛型主機(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,我們之前也介紹過(guò)其本質(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ì)看過(guò)了WebApplication.CreateBuilder(args).Build()通過(guò)這種方式構(gòu)建出來(lái)的是一個(gè)WebApplication類(lèi)的實(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ò)展方法,我們這里簡(jiǎn)單列舉一下

中間件名稱(chēng)描述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 RedirectionHttps重定向中間件.app.UseHttpsRedirection()
HTTP Strict Transport Security (HSTS)特殊響應(yīng)頭的安全增強(qiáng)中間件.app.UseHsts()
Request LoggingHTTP請(qǐng)求和響應(yīng)日志中間件.app.UseHttpLogging()
Response Caching輸出緩存中間件.app.UseResponseCaching()
Response Compression響應(yīng)壓縮中間件.app.UseResponseCompression()
SessionSession中間件app.UseSession()
Static Files靜態(tài)文件中間件.app.UseStaticFiles(), app.UseFileServer()
WebSocketsWebSocket支持中間件.app.UseWebSockets()

請(qǐng)求處理

我們可以使用WebApplication中的Map{HTTPMethod}相關(guān)的擴(kuò)展方法來(lái)處理不同方式的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}" );

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

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

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

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

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

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

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

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

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

路由約束

Minimal Api還支持在對(duì)路由規(guī)則的約束,這個(gè)和我們之前使用UseEndpoints的方式類(lèi)似,比如我約束路由參數(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è),也不是很多大概有如下幾種,簡(jiǎn)單的列一下表格

限制示例匹配示例說(shuō)明
int{id:int}123456789, -123456789匹配任何整數(shù)
bool{active:bool}true, false匹配 true 或 false. 忽略大小寫(xiě)
datetime{dob:datetime}2016-12-31, 2016-12-31 7:32pm匹配滿足DateTime類(lèi)型的值
decimal{price:decimal}49.99, -1,000.01匹配滿足 decimal類(lèi)型的值
double{height:double}1.234, -1,001.01e8匹配滿足 double 類(lèi)型的值
float{height:float}1.234, -1,001.01e8匹配滿足 float 類(lèi)型的值
guid{id:guid}CD2C1638-1638-72D5-1638-DEADBEEF1638匹配滿足Guid類(lèi)型的值
long{ticks:long}123456789, -123456789匹配滿足 long 類(lèi)型的值
minlength(value){username:minlength(4)}KOBE字符串長(zhǎng)度必須是4個(gè)字符
maxlength(value){filename:maxlength(8)}CURRY字符串長(zhǎng)度不能超過(guò)8個(gè)字符
length(length){filename:length(12)}somefile.txt字符串的字符長(zhǎng)度必須是12個(gè)字符
length(min,max){filename:length(8,16)}somefile.txt字符串的字符長(zhǎng)度必須介于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ū)分大小寫(xiě)。
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方式開(kāi)發(fā)的話,模型綁定是肯定會(huì)用到的,它的作用就是簡(jiǎn)化我們解析Http請(qǐng)求信息也是MVC框架的核心功能,它可以將請(qǐng)求信息直接映射成c#的簡(jiǎn)單類(lèi)型或者POCO上面。在Minimal Api的Map{HTTPMethod}相關(guān)方法中同樣可以進(jìn)行豐富的模型綁定操作,目前可以支持的綁定源有如下幾種

  • Route(路由參數(shù))

  • QueryString

  • Header

  • Body(比如JSON)

  • Services(即通過(guò)IServiceCollection注冊(cè)的類(lèi)型)

  • 自定義綁定

綁定示例

接下來(lái)我們首先看一下綁定路由參數(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ū)別的。

具體的類(lèi)也可以進(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中讀取它。

如果我們需要使用通過(guò)IServiceCollection注冊(cè)的具體實(shí)例,可以以通過(guò)模型綁定的方式進(jìn)行操作(很多人喜歡叫它方法注入,但是嚴(yán)格來(lái)說(shuō)卻是是通過(guò)定義模型綁定的相關(guān)操作實(shí)現(xiàn)的),而且還簡(jiǎ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)記了,前提是這些值的名稱(chēng)在不同的綁定來(lái)源中是唯一的,這種感覺(jué)讓我想到了剛開(kāi)始學(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ù)來(lái)源可以是

參數(shù)綁定來(lái)源
name路由參數(shù)
agequerystring
person依賴(lài)注入

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

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

它的模型綁定的值來(lái)源可以是

參數(shù)綁定來(lái)源
goodsbody里的json
person依賴(lài)注入

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

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

很多時(shí)候我們可能通過(guò)定義類(lèi)和方法的方式來(lái)聲明Map相關(guān)方法的執(zhí)行委托,這個(gè)時(shí)候呢依然可以進(jìn)行靈活的模型綁定,而且可能你也發(fā)現(xiàn)了,直接通過(guò)lambda表達(dá)式的方式雖然支持可空類(lèi)型,但是它不支持缺省參數(shù),也就是咱們說(shuō)的方法默認(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中直接編寫(xiě)相關(guān)邏輯的,因此需要用到HttpContext、HttpRequest、HttpResponse相關(guān)實(shí)例的時(shí)候沒(méi)辦法進(jìn)行直接操作,這個(gè)時(shí)候也需要通過(guò)模型綁定的方式獲取對(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采用了一種新的方式來(lái)自定義模型綁定,這種方式是一種基于約定的方式,無(wú)需提前注冊(cè),也無(wú)需集成什么類(lèi)或者實(shí)現(xiàn)什么接口,只需要在自定義的類(lèi)中存在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)大

接下來(lái)我們分別演示一下這兩種方式的使用方法,首先是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;
    }
}

這樣就可以完成簡(jiǎn)單的轉(zhuǎn)換綁定操作,從寫(xiě)法上我們可以看到,TryParse方法確實(shí)存在一定的限制,不過(guò)操作起來(lái)比較簡(jiǎn)單,這個(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é)們可以按需使用,得到的效果都是一樣的。如果類(lèi)中同時(shí)存在TryParseBindAsync方法,那么只會(huì)執(zhí)行BindAsync方法。

輸出結(jié)果

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

  • IResult 結(jié)果輸出,可以包含任何值得輸出,包含異步任務(wù)

  • Task<IResult>ValueTask<IResult>string  文本類(lèi)型輸出,包含異步任務(wù)

  • Task<string>ValueTask<string>T 對(duì)象類(lèi)型輸出,比如自定義的實(shí)體、匿名對(duì)象等,包含異步任務(wù) Task<T>ValueTask<T>

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

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

然后輸出一個(gè)對(duì)象類(lèi)型,對(duì)象類(lèi)型可以包含對(duì)象或集合甚至匿名對(duì)象,或者是咱們上面演示過(guò)的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類(lèi)型的結(jié)果,微軟也是很貼心的為我們統(tǒng)一封裝了一個(gè)靜態(tài)的Results類(lèi),方便我們使用,簡(jiǎn)單演示一下這種操作

//成功結(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類(lèi)其實(shí)是微軟幫我們多封裝了一層,它里面的所有靜態(tài)方法都是返回IResult的接口實(shí)例,這個(gè)接口有許多實(shí)現(xiàn)的類(lèi),滿足不同的輸出結(jié)果,比如Results.File("foo.text")方法其本質(zhì)就是返回一個(gè)FileContentResult類(lèi)型的實(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類(lèi)型的實(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代碼。微軟很貼心的為我們提供了專(zhuān)門(mén)擴(kuò)展Results的擴(kuò)展類(lèi)IResultExtensions基于這個(gè)類(lèi)我們才能完成IResult的擴(kuò)展

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

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

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

    /// <summary>
    /// 在該方法寫(xiě)自己的輸出邏輯即可
    /// </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類(lèi)中使用我們定義的擴(kuò)展方法了,使用方式如下

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

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

到此,關(guān)于“.NET6 Minimal API的使用方式是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI