Я всегда неохотно заявляю, что ошибка, которую я вижу, на самом деле является ошибкой .Net Core, но, потратив более 8 часов на изучение следующей ошибки, она выглядит для меня как ошибка .Net Core SignalR.Мне нужны методы для дальнейшего отслеживания и исправления.
Первое правило устранения ошибки заключается в том, чтобы попытаться создать минимальный объем кода, который может последовательно воспроизвести ошибку.Хотя я не могу воспроизвести его на небольшом стенде проекта, я усердно пытался сосредоточиться на происходящем.
У меня есть контроллер со следующим методом действия
[HttpPost]
[Route("/hack/ajax/start")]
public JsonResult AjaxStart([FromBody] JObject data) {
//A call to some method that does some work
return Json(new {
started = true
});
}
Вызов этого кода с помощью вызова jquery ajax или Postman работает каждый раз безупречно, если у меня нет каких-либо концентраторов SignalR Core 1.0, зарегистрированных в методе startup.cs.Однако, когда я регистрирую следующее в файле startup.cs, у меня возникают проблемы:
namespace App.Site.Home {
public class HackHub : Hub {
public async Task SendMessage(string status, string progress) {
await Clients.All.SendAsync("serverMsg", status, progress);
}
}
}
Startup.cs ConfigureServices
содержит
services.AddSignalR();
Startup.cs Configure
содержит
app.UseSignalR(routes => {
routes.MapHub<App.Site.Home.HackHub>("/hub/hack");
});
Если бы я закомментировал одну строку выше routes.MapHub<App.Site.Home.HackHub>("/hub/hack");
, то все работало бы хорошо каждый раз.Однако с этой строкой (то есть зарегистрированный хаб SignalR), тогда самое интересное для меня, даже если у меня нет кода, выполняющегося на клиенте или сервере, который использует хаб!
Проблема в том,что иногда, когда делается HTTP-запрос POST для метода действия, описанного выше, что-то в .Net Core (SignalR ??) преобразует метод POST в Post, а затем, поскольку Post не является допустимым HTTP-методом, он преобразует его в пустой метод,А поскольку метод My action требует HTTP POST, возвращается код состояния 404.Многие HTTP POSTS для этой конечной точки работают нормально, но часто возникает проблема, которую я только что описал.
Чтобы убедиться, что мой клиентский код не является частью проблемы, я смог воспроизвести мою проблему, используя Postman для выполнения запросов.Чтобы убедиться, что POST действительно отправляется, а не Post, я использовал Fiddler, чтобы посмотреть, что происходит по проводам.Все это документировано ниже.
Вот первый запрос (который всегда работает), выполняемый почтальоном:
Вотвторой (идентичный!) запрос, выполненный через Postman, этот запрос привел к 404:
Вот каков первый запрос (тот, который работал правильно) в фиддлере выглядело так:
Вот как выглядел второй запрос в фиддлере:
Как видите, запросы идентичны.Но ответ, конечно, нет.
Поэтому, чтобы лучше понять, что видит сервер, я добавил следующий код в начало метода startup.cs Configure
.Из-за его размещения для запроса этот код запускается перед любым другим кодом приложения или промежуточным программным обеспечением.
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
//for debugging
app.Use(async (context, next) => {
if(context.Request.Method == "") {
string method = context.Request.Method;
string path = context.Request.Path;
IHttpRequestFeature requestFeature = context.Features.Get<IHttpRequestFeature>();
string kestralHttpMethod = requestFeature.Method;
string stop = path;
}
await next();
});
//more code here...
}
Для первого запроса request.Method был POST, как и следовало ожидать:
Но для второго запроса запроса. Метод был пустым !!
Чтобы исследовать это далее, я получил доступ к requestFeature и проверил там метод Http Method.Здесь вещи становятся действительно интересными.Если я просто наведу указатель мыши на свойство в отладчике, оно тоже будет пустым.
Но, если я разверну объект requestFeature и посмотрю на свойство Methodтам, это сообщение !!!
Это само по себе кажется сумасшествием.Как два вида свойства SAME в отладчике могут иметь разные значения ???!Казалось бы, какой-то код преобразовал POST в Post, и на каком-то уровне система знает, что Post не является допустимым http-методом, поэтому в некоторых представлениях этой переменной он преобразуется в пустую строку.Но это так странно!
Кроме того, через Postman и Fiddler мы ясно видели, что POST был отправлен, так как же он изменился на Post?Какой код это сделал?Я хотел бы заявить, что это не может быть мой код, так как я проверяю значение RequestFeature, прежде чем любой другой мой код, связанный с запросом, получит шанс на выполнение.Кроме того, если я закомментирую одну строку кода, которая регистрирует этот концентратор SignalR, то POST никогда не преобразуется в Post, и я никогда не получаю 404. Но с этим зарегистрированным концентратором SignalR я периодически получаю такое поведение.
Есть ли какие-либо SignalR или другие .net Core переключатели, которые я могу включить, чтобы получить лучшую информацию о трассировке или регистрации, чтобы увидеть, когда POST меняется на Post?Есть ли способ это исправить?