在 asp.net core 的中間件中返回具體的頁(yè)面的實(shí)現(xiàn)方法
前言
在 asp.net core 中,存在著中間件這一概念,在中間件中,我們可以比過濾器更早的介入到 http 請(qǐng)求管道,從而實(shí)現(xiàn)對(duì)每一次的 http 請(qǐng)求、響應(yīng)做切面處理,從而實(shí)現(xiàn)一些特殊的功能
在使用中間件時(shí),我們經(jīng)常實(shí)現(xiàn)的是鑒權(quán)、請(qǐng)求日志記錄、全局異常處理等等這種非業(yè)務(wù)性的需求,而如果你有在 asp.net core 中使用過 swashbuckle(swagger)、health check、mini profiler 等等這樣的組件的話,你會(huì)發(fā)現(xiàn),這些第三方的組件往往都提供了頁(yè)面,允許我們通過可視化的方式完成某些操作或?yàn)g覽某些數(shù)據(jù)
因?yàn)樽约阂残枰獙?shí)現(xiàn)類似的功能,雖然使用到的知識(shí)點(diǎn)很少、也很簡(jiǎn)單,但是在網(wǎng)上搜了搜也沒有專門介紹這塊的文檔或文章,所以本篇文章就來說明如何在中間件中返回頁(yè)面,如果你有類似的需求,希望可以對(duì)你有所幫助
Step by Step
最終實(shí)現(xiàn)的功能其實(shí)很簡(jiǎn)單,當(dāng)用戶跳轉(zhuǎn)到某個(gè)指定的地址后,自定義的中間件通過匹配到該路徑,從而返回指定的頁(yè)面,所以這里主要會(huì)涉及到中間件是如何創(chuàng)建,以及如何處理頁(yè)面中的靜態(tài)文件引用
因?yàn)檫@塊并不會(huì)包含很多的代碼,所以這里主要是通過分析 Swashbuckle.AspNetCore 的代碼,了解它是如何實(shí)現(xiàn)的這一功能,從而給我們的功能實(shí)現(xiàn)提供一個(gè)思路
在 asp.net core 中使用 Swashbuckle.AspNetCore 時(shí),我們通常需要在 Startup 類中針對(duì)組件做如下的配置,根據(jù)當(dāng)前程序的信息生成 json 文件 =》 公開生成的 json 文件地址 =》 根據(jù) json 文件生成可視化的交互頁(yè)面
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// 生成 swagger 配置的 json 文件
services.AddSwaggerGen(s =>
{
s.SwaggerDoc("v1", new OpenApiInfo
{
Contact = new OpenApiContact
{
Name = "Danvic Wang",
Url = new Uri("https://yuiter.com"),
},
Description = "Template.API - ASP.NET Core 后端接口模板",
Title = "Template.API",
Version = "v1"
});
// 參數(shù)使用駝峰的命名方式
s.DescribeAllParametersInCamelCase();
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 公開 swagger 生成的 json 文件節(jié)點(diǎn)
app.UseSwagger();
// 啟用 swagger 可視化交互頁(yè)面
app.UseSwaggerUI(s =>
{
s.SwaggerEndpoint($"/swagger/v1/swagger.json",
$"Swagger doc v1");
});
}
}
可以看到最終呈現(xiàn)給用戶的頁(yè)面,其實(shí)是在 Configure 方法中通過調(diào)用 UseSwaggerUI 方法來完成的,這個(gè)方法是在 Swashbuckle.AspNetCore.SwaggerUI 這個(gè)程序集中,所以這里直接從 github 上找到對(duì)應(yīng)的文件夾,clone 下源代碼,來看下是如何實(shí)現(xiàn)在中間件中返回特定的頁(yè)面
在 clone 下的代碼中,排除掉一些 c#、node.js 使用到的項(xiàng)目性文件,可以看到整個(gè)項(xiàng)目中的文件按照功能可以分為三大塊,其中最核心的則是在 SwaggerUIMiddleware 類中,因此,這里主要聚焦在這個(gè)中間件類的實(shí)現(xiàn)

在一個(gè) asp.net core 中間件中,核心的處理邏輯是在 Invoke/InvokeAsync 方法中,結(jié)合我們使用 swagger 時(shí)的場(chǎng)景,可以看到,在將組件中所包含的頁(yè)面呈現(xiàn)給用戶時(shí),主要存在如下兩個(gè)處理邏輯
1、當(dāng)匹配到用戶訪問的是 /swagger 時(shí),返回 301 的 http 狀態(tài)碼,瀏覽器重定向到 /swagger/index.html,從而再次觸發(fā)該中間件的執(zhí)行
2、當(dāng)匹配到請(qǐng)求的地址為 /swagger/index.html 時(shí),將嵌入到程序集中的文件通過 stream 流的形式獲取到,轉(zhuǎn)換成字符串,再指定請(qǐng)求的響應(yīng)的類型為 text/html,從而實(shí)現(xiàn)將頁(yè)面返回給用戶
public async Task Invoke(HttpContext httpContext)
{
var httpMethod = httpContext.Request.Method;
var path = httpContext.Request.Path.Value;
// If the RoutePrefix is requested (with or without trailing slash), redirect to index URL
if (httpMethod == "GET" && Regex.IsMatch(path, $"^/?{Regex.Escape(_options.RoutePrefix)}/?$"))
{
// Use relative redirect to support proxy environments
var relativeRedirectPath = path.EndsWith("/")
? "index.html"
: $"{path.Split('/').Last()}/index.html";
RespondWithRedirect(httpContext.Response, relativeRedirectPath);
return;
}
if (httpMethod == "GET" && Regex.IsMatch(path, $"^/{Regex.Escape(_options.RoutePrefix)}/?index.html$"))
{
await RespondWithIndexHtml(httpContext.Response);
return;
}
await _staticFileMiddleware.Invoke(httpContext);
}
這里需要注意,因?yàn)轭愃朴谶@種功能,我們可能會(huì)打包成獨(dú)立的 nuget 包,然后通過 nuget 進(jìn)行引用,所以為了能夠正確獲取到頁(yè)面及其使用到的靜態(tài)資源文件,我們需要將這些靜態(tài)文件的屬性修改成嵌入的資源,從而在打包時(shí)可以包含在程序集中
對(duì)于網(wǎng)頁(yè)來說,在引用這些靜態(tài)資源文件時(shí)存在一種相對(duì)的路徑關(guān)系,因此,這里在中間件的構(gòu)造函數(shù)中,我們需要將頁(yè)面需要使用到的靜態(tài)文件,通過構(gòu)建 StaticFileMiddleware 中間件,將文件映射與網(wǎng)頁(yè)相同的 /swagger 路徑下面,從而確保頁(yè)面所需的資源可以正確加載
public class SwaggerUIMiddleware
{
private const string EmbeddedFileNamespace = "Swashbuckle.AspNetCore.SwaggerUI.node_modules.swagger_ui_dist";
private readonly SwaggerUIOptions _options;
private readonly StaticFileMiddleware _staticFileMiddleware;
public SwaggerUIMiddleware(
RequestDelegate next,
IHostingEnvironment hostingEnv,
ILoggerFactory loggerFactory,
SwaggerUIOptions options)
{
_options = options ?? new SwaggerUIOptions();
_staticFileMiddleware = CreateStaticFileMiddleware(next, hostingEnv, loggerFactory, options);
}
private StaticFileMiddleware CreateStaticFileMiddleware(
RequestDelegate next,
IHostingEnvironment hostingEnv,
ILoggerFactory loggerFactory,
SwaggerUIOptions options)
{
var staticFileOptions = new StaticFileOptions
{
RequestPath = string.IsNullOrEmpty(options.RoutePrefix) ? string.Empty : $"/{options.RoutePrefix}",
FileProvider = new EmbeddedFileProvider(typeof(SwaggerUIMiddleware).GetTypeInfo().Assembly, EmbeddedFileNamespace),
};
return new StaticFileMiddleware(next, hostingEnv, Options.Create(staticFileOptions), loggerFactory);
}
}

當(dāng)完成了頁(yè)面的呈現(xiàn)后,因?yàn)橐话阄覀儠?huì)創(chuàng)建一個(gè)單獨(dú)的類庫(kù)來實(shí)現(xiàn)這些功能,在頁(yè)面中,可能會(huì)包含前后端的數(shù)據(jù)交互,由于我們?cè)谒拗鞯?API 項(xiàng)目中已經(jīng)完成了對(duì)于路由規(guī)則的設(shè)定,所以這里只需要在類庫(kù)中通過 nuget 引用 Microsoft.AspNetCore.Mvc.Core ,然后與 Web API 一樣的定義 controller,確保這個(gè)中間件在宿主程序的調(diào)用位于路由匹配規(guī)則之后即可
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
// Endpoint 路由規(guī)則設(shè)定
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
// 自定義中間件
app.UseMiddleware<SampleUIMiddleware>();
}
參考:http://www.dbjr.com.cn/article/116369.htm
總結(jié)
到此這篇關(guān)于在 asp.net core 的中間件中返回具體的頁(yè)面的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)asp.net core 中間件返回具體的頁(yè)面內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- ASP.NET Core 應(yīng)用程序中的靜態(tài)文件中間件的實(shí)現(xiàn)
- .Net Core中間件之靜態(tài)文件(StaticFiles)示例詳解
- .net core異常中間件的使用
- ASP.NET Core中間件初始化的實(shí)現(xiàn)
- 詳解ASP.NET Core 中基于工廠的中間件激活的實(shí)現(xiàn)方法
- ASP.NET Core自定義中間件如何讀取Request.Body與Response.Body的內(nèi)容詳解
- .net core webapi通過中間件獲取請(qǐng)求和響應(yīng)內(nèi)容的方法
- 利用.net core實(shí)現(xiàn)反向代理中間件的方法
- 如何給asp.net core寫個(gè)中間件記錄接口耗時(shí)
- ASP.NET Core中間件計(jì)算Http請(qǐng)求時(shí)間示例詳解
- ASP.NET Core應(yīng)用錯(cuò)誤處理之ExceptionHandlerMiddleware中間件呈現(xiàn)“定制化錯(cuò)誤頁(yè)面”
- .net core靜態(tài)中間件的使用
相關(guān)文章
asp.net core配合vue實(shí)現(xiàn)后端驗(yàn)證碼邏輯
網(wǎng)上的前端驗(yàn)證碼邏輯總感覺不安全,驗(yàn)證碼建議還是使用后端配合驗(yàn)證。本文主要介紹了asp.net core配合vue實(shí)現(xiàn)后端驗(yàn)證碼邏輯,感興趣的可以了解一下2021-06-06
asp.net簡(jiǎn)單實(shí)現(xiàn)頁(yè)面換膚的方法
這篇文章主要介紹了asp.net簡(jiǎn)單實(shí)現(xiàn)頁(yè)面換膚的方法,可實(shí)現(xiàn)給頁(yè)面動(dòng)態(tài)添加樣式的功能,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-12-12
在Apache環(huán)境下成功的運(yùn)行ASP.NET的注意事項(xiàng)
在Apache環(huán)境下成功的運(yùn)行ASP.NET的注意事項(xiàng)...2007-08-08
ASP.NET?MVC5網(wǎng)站開發(fā)之用戶資料的修改和刪除3(七)
這篇文章主要為大家詳細(xì)介紹了ASP.NET?MVC5網(wǎng)站開發(fā)之用戶資料的修改和刪除,感興趣的小伙伴們可以參考一下2016-08-08
asp.net 數(shù)據(jù)訪問層 存儲(chǔ)過程分頁(yè)語(yǔ)句
在asp.net 網(wǎng)頁(yè)中如果在業(yè)務(wù)邏輯層分頁(yè)在使用PagedDataSource對(duì)象,但如果數(shù)據(jù)記錄過多,使用它會(huì)嚴(yán)重的損害應(yīng)用程序的性能.2009-12-12

