我可以通过构造函数中的DI在我的.NET Core WebAPI控制器中访问我的IHubContext<MyHub>
精细和花花公子,但我也想在其他地方访问它。
具体来说,当我从RabbitMQ使用消息时,有时我想通过_myHubContext.Clients.All.InvokeAsync()
更新客户端,但我无法弄清楚如何获取它。
我也在寻找在控制器之外做这种事情的文档时遇到了问题。
任何帮助都将不胜感激。
修改
要添加一些细节,以及我的问题可能产生的原因,我正在尝试访问ConfigureServices
类中的IHubContext(以及我在Startup
中注册的一些服务),特别是在IApplicationLifetime
ApplicationStarted
和ApplicationStopped
期间调用RabbitMQ使用者的连接和断开方法。
我是正确的猜测我可能无法访问Startup
课程中的注册服务?如果是这样,我将如何开始这些服务?
更新
将services.AddSignalR()
以及在启动时调用的一些服务移至WebHost.ConfigureServices
中的Program.cs
解决了我的一些问题,但当然还有更多。
当我从RabbitMQ收到消息时,我的JS客户端上没有收到任何消息,但我的客户端已成功连接。 “很奇怪......”我想。为了获得更多信息,我在控制器中连接了一个GET动作,通过SignalR Hub
发送了一些内容。每当我打电话给GET时,它都有效...... IHubContext<MyHub>
。我通过RabbitMQ监听器中的构造函数得到hubContext
,就像我对控制器一样。
新问题:在控制器中注入的内容与在启动时注册的服务中注入的内容不同吗?怎么这样,我该如何克服呢?
一些代码可以使用它......
摘录自Program.cs
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseIISIntegration()
.ConfigureServices(services => {
services.AddSignalR();
services.AddTransient<ISubscriber, Subscriber>();
services.AddTransient<IDataService, DataService>();
services.AddTransient<IHealthCheckProcessor, HealthCheckProcessor>();
services.AddTransient<INodeProcessor, NodeProcessor>();
})
.UseStartup<Startup>()
.Build();
来自Startup.cs
public class Startup
{
public Startup(IConfiguration _configuration, ISubscriber _subscriber)
{
configuration = _configuration;
subscriber = _subscriber;
}
public IConfiguration configuration { get; }
public ISubscriber subscriber { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(builder => builder
// CORS stuff);
app.UseSignalR(routes =>
{
routes.MapHub<StatusHub>("Status");
});
app.UseMvc();
applicationLifetime.ApplicationStarted.Register(OnStartup);
applicationLifetime.ApplicationStopping.Register(OnShutdown);
}
private void OnStartup() {
// MessageBroker stuff
subscriber.Start(messageBroker);
}
private void OnShutdown() {
subscriber.Stop();
}
}
来自Subscriber.cs
public class Subscriber : ISubscriber {
public static IConnection connection;
public static IModel channel;
public IHubContext<StatusHub> hubContext;
public static IHealthCheckProcessor healthCheckProcessor;
public static INodeProcessor nodeProcessor;
public Subscriber(IHubContext<StatusHub> _hubContext, INodeProcessor _nodeProcessor, IHealthCheckProcessor _healthCheckProcessor)
{
connection = new ConnectionFactory().CreateConnection();
channel = connection.CreateModel();
hubContext = _hubContext;
nodeProcessor = _nodeProcessor;
healthCheckProcessor = _healthCheckProcessor;
}
public void Start(MessageBroker messageBroker)
{
var factory = new ConnectionFactory() { HostName = messageBroker.URL }.CreateConnection();
foreach (Queue queue in messageBroker.Queues)
{
channel.QueueDeclare(
queue: queue.Name,
durable: queue.Durable,
exclusive: queue.Exclusive,
autoDelete: queue.AutoDelete,
arguments: null
);
EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
byte[] body = ea.Body;
string message = Encoding.UTF8.GetString(body);
RouteMessage(queue, message);
};
channel.BasicConsume(
queue: queue.Name,
autoAck: queue.AutoAck,
consumer: consumer
);
hubContext.Clients.All.InvokeAsync("Send", "It worked - from the subscriber");
}
}
public void RouteMessage(Queue queue, string message) {
if(queue.Name == "discovery") {
nodeProcessor.Process(message);
}
if(queue.Name == "health") {
healthCheckProcessor.Process(message);
}
}
public void Stop()
{
Console.WriteLine("Terminating connection to RabbitMQ instance.");
channel.Close(200, "Goodbye");
connection.Close();
}
}
来自HealthCheckProcessor.cs
public class HealthCheckProcessor : IHealthCheckProcessor {
private IDataService dataService;
private IHubContext<StatusHub> hubContext;
public HealthCheckProcessor(IDataService _dataService, IHubContext<StatusHub> _hubContext)
{
dataService = _dataService;
hubContext = _hubContext;
}
public void Process(string message) {
HealthCheck health = JsonConvert.DeserializeObject<HealthCheck>(message);
Node node = dataService.GetSingle(health.NodeId);
node.Health = health;
dataService.Update(node);
Console.WriteLine("It's sending.");
hubContext.Clients.All.InvokeAsync("Send", "It worked - from the processor");
}
}
来自Controller:
[Route("api/[controller]")]
public class MyController: Controller
{
private IDataService _dataService;
private readonly IConfiguration configuration;
private static IHubContext<StatusHub> hubContext;
public NodesController(IConfiguration config, IDataService dataService, IHubContext<StatusHub> _hubContext)
{
_dataService = dataService;
configuration = config;
hubContext = _hubContext;
}
[HttpGet]
public string Get()
{
hubContext.Clients.All.InvokeAsync("Send", "Blarg!");
return "Well, I tried.";
}
}
答案 0 :(得分:2)
您正在尝试访问请求时无法使用的服务。
java.lang.ClassCastException: application.model.Usuario cannot be cast to application.model.Usuario
at application.core.user.dao.implementation.UserDaoImplementation.findById(UserDaoImplementation.java:35)
at application.core.user.service.implementation.UserServiceImplementation.findById(UserServiceImplementation.java:17)
at application.security.UserDetailsApp.loadUserByUsername(UserDetailsApp.java:34)
at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:114)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:144)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
专门在Configure
之后调用,以便可以访问注册的所有服务。
ConfigureServices
现在,您应该能够在构建主机时删除便利public class Startup {
public Startup(IConfiguration _configuration) {
configuration = _configuration;
}
public IConfiguration configuration { get; }
public void ConfigureServices(IServiceCollection services) {
services.AddCors();
services.AddMvc();
services.AddSignalR();
services.AddTransient<ISubscriber, Subscriber>();
services.AddTransient<IDataService, DataService>();
services.AddTransient<IHealthCheckProcessor, HealthCheckProcessor>();
services.AddTransient<INodeProcessor, NodeProcessor>();
}
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
IApplicationLifetime applicationLifetime,
IServiceProvider sp
) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseCors(builder => builder
// CORS stuff);
app.UseMvc();
app.UseSignalR(routes => {
routes.MapHub<StatusHub>("Status");
});
//At this point all the necessary dependencies have been registered and configured
var subscriber = sp.GetService<ISubscriber>();
applicationLifetime.ApplicationStarted.Register(() => OnStartup(subscriber));
applicationLifetime.ApplicationStopping.Register(() => OnShutdown(subscriber));
}
private void OnStartup(ISubscriber subscriber) {
// MessageBroker stuff
subscriber.Start(messageBroker);
}
private void OnShutdown(ISubscriber subscriber) {
subscriber.Stop();
}
}
。
ConfigureServices