MBi*_*irk 8 asp.net dependency-injection owin-middleware blazor blazor-server-side
我正在开发服务器端 Blazor 应用程序,并遇到了有关范围服务的一些问题。为了简单起见,我使用默认的 Blazor 模板(带有计数器的模板)重新创建了我的问题。
我有一个服务“CounterService”,它将计数器初始化为 1 并公开该计数器以及递增它的方法。非常基本:
public class CounterService
{
public int Counter { get; private set; }
public CounterService()
{
Counter = 1;
}
public void IncrementCounter()
{
Counter++;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我在 Startup.cs 中将此计数器注册为范围服务:`services.AddScoped()
然后我有一个自定义 ASP.NET 中间件,在本例中为“CounterInitializerMiddleware”。
public class CounterInitializerMiddleware
{
public CounterInitializerMiddleware(RequestDelegate next)
{
_next = next;
}
public RequestDelegate _next { get; }
public async Task Invoke(HttpContext context, CounterService counterService)
{
Console.WriteLine($"CounterInitializer invoked from request path: {context.Request.Path.Value}");
counterService.IncrementCounter();
counterService.IncrementCounter();
await _next(context);
}
}
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseCounterInitializer(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<CounterInitializerMiddleware>();
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,它是一个中间层,用于增加计数器,以便当我将服务注入到我的组件中时,它从 3 而不是 1 开始。我在 Startup.cs 的配置方法中注册它:`app.UseCounterInitializer();
当我启动应用程序时,此中间件层被调用 4 次(请注意,它的 RenderMode 设置为 ServerPreRendered): 在页面加载请求和 _blazor 请求时:
CounterInitializer invoked from request path: /counter
CounterInitializer invoked from request path: /_blazor/disconnect
CounterInitializer invoked from request path: /_blazor/negotiate
CounterInitializer invoked from request path: /_blazor
Run Code Online (Sandbox Code Playgroud)
范围服务已注入,一切看起来都很好。
然后,如果我有一个注入了 CounterService 的组件,那么范围似乎会变得混乱。如果我查看 OnInitialized 方法,就会发现该方法被调用了两次。一次在预渲染期间,一次在正常渲染期间。在预渲染执行时,CounterService 将 Counter 按预期设置为 3,因为它是通过 CounterInitializerMiddleware 进行的。但是,在渲染执行期间,CounterService 会重新生成。因此,正常渲染的范围和通过中间件的请求的范围似乎是不同的。我认为组件的范围将绑定到由中间件处理的“_blazor”-signalR 连接。
谁能弄清楚发生了什么事并帮助我了解如何完成我想做的事情?
最好的,马蒂亚斯
编辑:只是为了澄清。我真正的用例是完全不同的,反例只是展示问题的简化案例,并且更容易重现(我希望)。
小智 1
我遇到了同样的问题,需要一个快速的解决方法。
解决方法是从 HttpContext 获取服务,这是一种反模式,但总比没有好。
class YourClass
{
private readonly SomeMiddlewareScopedService _service;
public YourClass(SomeMiddlewareScopedServiceservice)
{
_service = service;
}
}
Run Code Online (Sandbox Code Playgroud)
解决方法:
class YourClass
{
private readonly SomeMiddlewareScopedService _service;
public YourClass(IHttpContextAccessor contextAccessor)
{
_service= (SomeMiddlewareScopedService)contextAccessor.HttpContext.RequestServices.GetService(typeof(SomeMiddlewareScopedService));
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记添加到您的构建器中:
builder.Services.AddHttpContextAccessor();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1447 次 |
| 最近记录: |