ASP.NET 扩展支持
本文介绍将如何在Nebula中实现与ASP.NET相关的一些扩展场景:
- 添加 MVC Filter
- 调整 MVC UrlRouting
- 引入新组件
- 添加 Middleware/RequestDelegate
添加 MVC Filter
你可以开发一个符合 ASP.NET 要求的 MVC Filter,例如:
public class MyActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// 过程省略
}
然后,在NebulaBehavior的继承类中注册它,例如:
public class MyNebulaBehavior : NebulaBehavior
{
public override void SetMvcOptions(MvcOptions opt)
{
opt.Filters.Add(typeof(MyActionFilter));
}
最后,在 AppStartOption 中引 MyNebulaBehavior,例如:
public class Program
{
public static void Main(string[] args)
{
AppStartOption startOption = new AppStartOption {
NebulaBehavior = new MyNebulaBehavior()
};
AppStartup.RunAsWebsite("XDemo.WebSiteApp", args, startOption);
}
}
注意:继承NebulaBehavior的子类必须使用上面的方式来使用它,本文后面将不再重复指出。
调整 MVC UrlRouting
以下代码是 NebulaBehavior 中的 UrlRouting 默认实现:
public virtual void ConfigureUrlRouting(WebApplication app)
{
app.UseRouting();
app.MapControllers();
if( AppStartup.StartOption.EnableDefaultHomePage ) {
app.MapGet("/", ShowHomePage);
}
}
说明:
- 建议不要覆盖重写这个方法,可以在调用 base 方法的 before, after 中添加路由规则
- 或者采用 RequestDelegate 的方式来拦截请求实现路由规则
引入新组件
首先要清楚,在 ASP.NET Core 的设计中,一个组件的引入被分为2个阶段:
- 在Ioc容器中注入服务(组件),对应 Startup.ConfigureServices 方法
- 配置ASP.NET管道(可选步骤),对应 Startup.Configure 方法
在Nebula框架中,不再需要每个项目再维护Startup类型,
只需要开发一个新类型从BaseAppStarter继承,然后选择要实现的方法即可。
BaseAppStarter 提供以下方法用于定制ASPNETCORE的启动过程:
- PreNebulaInit:默认行为:什么也不做(等着你来填空)
- PostNebulaInit:默认行为:什么也不做(等着你来填空)
- PreConfigureServices:默认行为:什么也不做(等着你来填空)
- PostConfigureServices:默认行为:什么也不做(等着你来填空)
- PreConfigureWeb:默认行为:什么也不做(等着你来填空)
- PostConfigureWeb:默认行为:什么也不做(等着你来填空)
- PreBuildWebHost:默认行为:什么也不做(等着你来填空)
- PostBuildWebHost:默认行为:什么也不做(等着你来填空)
- PreApplicationInit:默认行为:什么也不做(等着你来填空)
- PostApplicationInit:默认行为:什么也不做(等着你来填空)
这里以引入 SignalR 为例演示整个开发过程,完整示例如下:
public class ImportSignalrStarter : BaseAppStarter
{
public override void ConfigureServices(IServiceCollection services)
{
string conn = ConfigClient.Instance.GetSetting("Redis.Connection");
services.AddSignalR(option => {
option.EnableDetailedErrors = true;
option.MaximumReceiveMessageSize = 1024 * 1024;
option.HandshakeTimeout = TimeSpan.FromSeconds(60);
option.StreamBufferCapacity = 5000;
}).AddNewtonsoftJsonProtocol()
.AddStackExchangeRedis(conn);
}
public override void PostConfigureWeb(WebApplication app)
{
app.UseEndpoints(endpoints => {
endpoints.MapHub<NotifyHub>("/v20/api/ws/notify", option => {
option.Transports = HttpTransportType.WebSockets;
});
});
}
}
说明:
- 一个项目中,可以有多个 BaseAppStarter 的继承类
- BaseAppStarter 的继承类必须是 public 的可见性,框架会自动识别并调用。
- BaseAppStarter 的继承类可以出现在类库中,用来构造完整的业务模块(支持所谓的模块化开发)
添加 Middleware/RequestDelegate
开发 MyRequestDelegate,示例代码如下:
public class MyRequestDelegate
{
private readonly Microsoft.AspNetCore.Http.RequestDelegate _next;
private long _requestCount = 0;
public MyRequestDelegate(Microsoft.AspNetCore.Http.RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(Microsoft.AspNetCore.Http.HttpContext httpContext)
{
long count = Interlocked.Increment(ref _requestCount);
httpContext.Response.Headers.Add("x-ReuestCount", count.ToString());
await _next(httpContext);
}
}
开发一个新类型,从 BaseAppStarter 继承,
public class XxxAppStarter : BaseAppStarter
{
public override void PostConfigureWeb(WebApplication app)
{
app.UseMiddleware<MyRequestDelegate>();
}
}
这样就可以了,框架会自动识别!