Я создаю плагины (проекты) для NopCommerce (проект .NET MVC). У меня есть два независимых плагина (проекта). Один для предоставления API, а другой для поддержки в чате в реальном времени. Для чата в реальном времени я использую SignalR. И стек вызовов ошибок -
Не могу решить эту проблему. Ниже приведен файл запуска моего плагина (проекта) API.
А это файл запуска моего плагина чата (проекта) в реальном времени:
А это MessageHub из проекта плагина чата в реальном времени.
Microsoft.AspNetCore.SignalR.HubConnectionHandler: Error: Error when dispatching 'OnConnectedAsync' on hub.
System.InvalidOperationException: OnStarting cannot be set because the response has already started.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.OnStarting(Func`2 callback, Object state)
at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.InitializeHandlerAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)
at Nop.Services.Authentication.CookieAuthenticationService.GetAuthenticatedCustomerAsync()
at Nop.Plugin.API.Services.BearerTokenOrCookieAuthenticationService.GetAuthenticatedCustomerAsync()
at Nop.Web.Framework.WebWorkContext.SetCurrentCustomerAsync(Customer customer)
at Nop.Web.Framework.WebWorkContext.GetCurrentCustomerAsync()
at Nop.Plugin.Widgets.RealTimeChat.Hubs.MessageHub.IsAuthenticated() in Documents\nopCommerce\src\Plugins\Nop.Plugin.Widgets.RealTimeChat\Hubs\MessageHub.cs:line 63
at Nop.Plugin.Widgets.RealTimeChat.Hubs.MessageHub.OnConnectedAsync() in nopCommerce\src\Plugins\Nop.Plugin.Widgets.RealTimeChat\Hubs\MessageHub.cs:line 23
at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnConnectedAsync(HubConnectionContext connection)
at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnConnectedAsync(HubConnectionContext connection)
at Microsoft.AspNetCore.SignalR.HubConnectionHandler`1.RunHubAsync(HubConnectionContext connection)
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint '/messageHub'
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, jwtBearerOptions =>
{
jwtBearerOptions.TokenValidationParameters = //token validation parameter
jwtBearerOptions.Events = new JwtBearerEvents
{
OnChallenge = context =>
{
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(new { error = "Unauthorized access" });
return context.Response.WriteAsync(result);
}
};
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
AddAuthorizationPipeline(services);
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
services.Configure<MvcNewtonsoftJsonOptions>(options =>
{
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});
services.AddControllers();
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "nop commerce mobile api"
});
});
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigSwaggerOptions>();
services.AddCors(opt =>
{
opt.AddPolicy(name: "CorsPolicy", builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
public void Configure(IApplicationBuilder app)
{
var environment = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>();
var rewriteOptions = new RewriteOptions().AddRewrite("api/token", "/token", true);
app.UseRewriter(rewriteOptions);
app.UseCors("CorsPolicy");
app.MapWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), a =>
{
a.Use(async (context, next) =>
{
context.Request.EnableBuffering();
await next();
});
// Authentication and authorization
a.UseAuthentication();
a.UseAuthorization();
// Routing and endpoints
a.UseRouting();
a.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
});
// Swagger configuration
app.UseSwagger(options => options.RouteTemplate = "api/swagger/{documentName}/swagger.json");
app.UseSwaggerUI(options =>
{
options.RoutePrefix = "api/swagger";
options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "Nop API v1");
});
}
public void Configure(IApplicationBuilder application)
{
application.UseRouting();
application.UseAuthorization();
application.UseEndpoints(endpoints =>
{
endpoints.MapHub<MessageHub>(RealTimeChatConstants.HubConnectionRoute);
});
}
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddSignalR(r =>
{
r.EnableDetailedErrors = true;
});
//register services
}
public class MessageHub : Hub
{
//fields and ctor
public override async Task OnConnectedAsync()
{
if (!await IsAuthenticated())
{
return;
}
var currentCustomer = await _workContext.GetCurrentCustomerAsync();
var existingUser = _connectedUsers.FirstOrDefault(x => x.UserId == currentCustomer.Id);
if (existingUser == null)
{
_connectedUsers.Add(new UserConnection { ConnectionId = Context.ConnectionId, UserId = currentCustomer.Id });
}
else
{
existingUser.ConnectionId = Context.ConnectionId;
}
await base.OnConnectedAsync();
}
}
Кир
Вопрос задан4 апреля 2024 г.