Введение
При построении веб -приложения .NET он обычно использует комбинацию UseExceptionHandler и UseStatusCodePagesWithReExecute в вашем Startup.cs Чтобы обслуживать страницы ошибок, удобные для пользователя:
app.UseExceptionHandler("/errorhandler/500");
app.UseStatusCodePagesWithReExecute("/errorhandler/{0}");
Это работает плавно – даже для оптимизированных решений CMS. Тем не менее, мы недавно обнаружили предостережение, работая над проектом, включающим пользовательские конечные точки API. Оказывается, оптимизируется имеет свое собственное скрытое поведение в отношении обработки ошибок, и оно может молча мешать вашим тщательно настроенным трубопроводам.
Проблема: пользовательские ошибки для сегмента API
У нас был маршрут API, который намеренно Возвращает необработанные коды статуса HTTP (например, 401 несанкционированный) в зависимости от бизнес -логики. Ожидаемое поведение состояло в том, чтобы вернуть фактический код ответа HTTP, а не дружественную страницу ошибок HTML.
Однако один раз UseStatusCodePagesWithReExecute включено, даже конечные точки API, как /my/custom/api Поиск, и вы получите ответ HTML -ошибки, когда ваш API возвращает 401.
Итак, мы добавили условную логику:
app.UseWhen(
context => !context.Request.Path.StartsWithSegments("/my/custom/api"),
appBuilder =>
{
appBuilder.UseExceptionHandler("/errorhandler/500");
appBuilder.UseStatusCodePagesWithReExecute("/errorhandler/{0}");
});
Это работает –Пока вы не пойдете на производствоПолем
Сюрприз: оптимизируемые крючки в своем собственном промежуточном программном обеспечении
К нашему удивлению, наш API все еще возвращал страницу ошибок Optimizely в производстве. После некоторого копания мы обнаружили, что Оптимизируемо CMS автоматически регистрирует свое собственное исключение и обработку кода состояниянезависимо от того, что вы настраиваете.
Это происходит, когда вы звоните .AddCms()-конкретно, .AddCmsUI() Внутренне регистрирует следующую услугу:
services.AddStartupFilter();
Этот фильтр выглядит так:
public Action Configure(Action nextAction)
{
return app =>
{
if (app.ApplicationServices.GetRequiredService().IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseStatusCodePagesWithReExecute("/Util/Errors/Error{0}");
app.UseExceptionHandler("/Util/Errors/Error500");
}
nextAction(app);
};
}
Итак, оптимизировать всегда провода в собственных обработчиках ошибок – после ваших.
Наше решение: удалить фильтр запуска
Там нет публичной конфигурации, чтобы отключить такое поведение. Класс есть internalпоэтому вы не можете переопределить или настроить его. Мы должны были самостоятельно удалить его из коллекции услуг:
var errorStartupFilterServiceDescriptor = services
.FirstOrDefault(descriptor => descriptor.ImplementationType?.Name == "ErrorsStartupFilter");
if (errorStartupFilterServiceDescriptor != null)
{
services.Remove(errorStartupFilterServiceDescriptor);
}
Делая это в начале ConfigureServicesВы предотвращаете инъекцию обработчиков ошибок Optimizely, снова предоставив вам полный контроль над трубопроводом.
Последние мысли
Это один из тех “Framework Magic vs. Control” Control “ ситуации. Его легко пропустить, потому что все, кажется, работает на местном уровне – до тех пор, пока производство не разоблачит конфликт.
Надеюсь, это экономит кого -то несколько часов отладки!
По теме

