Нужна полная выборка для обработки необработанных исключений с использованием "ExceptionHandler" в ASP.NET Web Api?
Я проверил эту ссылку
http://www.asp.net/web-api/overview/web-api-routing-and-actions/web-api-global-error-handling.
В этой ссылке они упомянули так:
class OopsExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
context.Result = new TextPlainErrorResult
{
Request = context.ExceptionContext.Request,
Content = "Oops! Sorry! Something went wrong." +
"Please contact [email protected] so we can try to fix it."
};
}
private class TextPlainErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response =
new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.Content = new StringContent(Content);
response.RequestMessage = Request;
return Task.FromResult(response);
}
}
}
Я не знаю, как назвать этот класс в моих действиях веб-API. Так может ли кто-нибудь дать мне полный образец, используя этот ExceptionHandler
.
Ответы
Ответ 1
В конфигурации вашего WebApi вам нужно добавить строку:
config.Services.Replace(typeof (IExceptionHandler), new OopsExceptionHandler());
Также убедитесь, что вы создали базовый класс ExceptionHandler, который реализует IExceptionHandler:
public class ExceptionHandler : IExceptionHandler
{
public virtual Task HandleAsync(ExceptionHandlerContext context,
CancellationToken cancellationToken)
{
if (!ShouldHandle(context))
{
return Task.FromResult(0);
}
return HandleAsyncCore(context, cancellationToken);
}
public virtual Task HandleAsyncCore(ExceptionHandlerContext context,
CancellationToken cancellationToken)
{
HandleCore(context);
return Task.FromResult(0);
}
public virtual void HandleCore(ExceptionHandlerContext context)
{
}
public virtual bool ShouldHandle(ExceptionHandlerContext context)
{
return context.ExceptionContext.IsOutermostCatchBlock;
}
}
Обратите внимание, что это будет иметь дело только с исключениями, которые не обрабатываются в другом месте (например, с помощью фильтров Исключения).
Ответ 2
Вам не нужно самостоятельно реализовывать механизм минимального уровня IExceptionHandler.
Вместо этого вы можете просто наследовать ExceptionHandler и переопределить Handle.
public class MyExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
//TODO: Do what you need to do
base.Handle(context);
}
}
ExceptionHandler реализует IExceptionHandler и управляет основные механизмы ядра (например, async и это исключение должно быть обработано или нет).
Используйте свой обработчик исключений:
config.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());
Источник
Эта страница объясняет, как реализовать IExceptionHandler, но есть некоторые опечатки, и код не отражает последнюю версию WebApi.
Нет документации о пространстве имен System.Web.Http.ExceptionHandling
(немного на NuDoq).
Итак, с помощью . NET-сборщик декомпилятора, посмотрев исходный код GitHub, я видел класс ExceptionHandler
, который реализует IExceptionHandler
и имеет некоторые виртуальные методы.
ExceptionHandler выглядит следующим образом:
namespace System.Web.Http.ExceptionHandling
{
/// <summary>Represents an unhandled exception handler.</summary>
public abstract class ExceptionHandler : IExceptionHandler
{
/// <returns>Returns <see cref="T:System.Threading.Tasks.Task" />.</returns>
Task IExceptionHandler.HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
ExceptionContext arg_14_0 = context.ExceptionContext;
if (!this.ShouldHandle(context))
{
return TaskHelpers.Completed();
}
return this.HandleAsync(context, cancellationToken);
}
/// <summary>When overridden in a derived class, handles the exception asynchronously.</summary>
/// <returns>A task representing the asynchronous exception handling operation.</returns>
/// <param name="context">The exception handler context.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
public virtual Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
this.Handle(context);
return TaskHelpers.Completed();
}
/// <summary>When overridden in a derived class, handles the exception synchronously.</summary>
/// <param name="context">The exception handler context.</param>
public virtual void Handle(ExceptionHandlerContext context)
{
}
/// <summary>Determines whether the exception should be handled.</summary>
/// <returns>true if the exception should be handled; otherwise, false.</returns>
/// <param name="context">The exception handler context.</param>
public virtual bool ShouldHandle(ExceptionHandlerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
ExceptionContext exceptionContext = context.ExceptionContext;
ExceptionContextCatchBlock catchBlock = exceptionContext.CatchBlock;
return catchBlock.IsTopLevel;
}
}
}
Вы можете ясно видеть, что ShouldHandle
реализовано с помощью ExceptionContextCatchBlock.IsTopLevel
и что HandleAsync
вызывает Handle
:)
Я надеюсь, что это поможет, пока не появится полная документация.
Ответ 3
Как сказал Джон Сюзиак, вам нужно использовать:
config.Services.Replace(typeof (IExceptionHandler), new OopsExceptionHandler());
Обратите внимание на вызов Replace
, а не Add
.
Причина этого в том, что касается статьи по этой ссылке:
Глобальная обработка ошибок в ASP.NET Web API 2
Обзор решений
Мы предоставляем две новые сменные сервисы, IExceptionLogger и IExceptionHandler, для регистрации и обработки необработанных исключений.
услуги очень похожи, с двумя основными отличиями:
Мы поддерживаем регистрацию нескольких журналов исключений, но только один обработчик исключений.
И поскольку уже зарегистрирован обработчик, по умолчанию вы не можете добавить другого.
public DefaultServices(HttpConfiguration configuration)
{
if (configuration == null)
throw System.Web.Http.Error.ArgumentNull("configuration");
this._configuration = configuration;
this.SetSingle<IActionValueBinder>((IActionValueBinder) new DefaultActionValueBinder());
this.SetSingle<IApiExplorer>((IApiExplorer) new ApiExplorer(configuration));
this.SetSingle<IAssembliesResolver>((IAssembliesResolver) new DefaultAssembliesResolver());
this.SetSingle<IBodyModelValidator>((IBodyModelValidator) new DefaultBodyModelValidator());
this.SetSingle<IContentNegotiator>((IContentNegotiator) new DefaultContentNegotiator());
this.SetSingle<IDocumentationProvider>((IDocumentationProvider) null);
this.SetMultiple<IFilterProvider>((IFilterProvider) new ConfigurationFilterProvider(), (IFilterProvider) new ActionDescriptorFilterProvider());
this.SetSingle<IHostBufferPolicySelector>((IHostBufferPolicySelector) null);
this.SetSingle<IHttpActionInvoker>((IHttpActionInvoker) new ApiControllerActionInvoker());
this.SetSingle<IHttpActionSelector>((IHttpActionSelector) new ApiControllerActionSelector());
this.SetSingle<IHttpControllerActivator>((IHttpControllerActivator) new DefaultHttpControllerActivator());
this.SetSingle<IHttpControllerSelector>((IHttpControllerSelector) new DefaultHttpControllerSelector(configuration));
this.SetSingle<IHttpControllerTypeResolver>((IHttpControllerTypeResolver) new DefaultHttpControllerTypeResolver());
this.SetSingle<ITraceManager>((ITraceManager) new TraceManager());
this.SetSingle<ITraceWriter>((ITraceWriter) null);
this.SetMultiple<ModelBinderProvider>((ModelBinderProvider) new TypeConverterModelBinderProvider(), (ModelBinderProvider) new TypeMatchModelBinderProvider(), (ModelBinderProvider) new KeyValuePairModelBinderProvider(), (ModelBinderProvider) new ComplexModelDtoModelBinderProvider(), (ModelBinderProvider) new ArrayModelBinderProvider(), (ModelBinderProvider) new DictionaryModelBinderProvider(), (ModelBinderProvider) new CollectionModelBinderProvider(), (ModelBinderProvider) new MutableObjectModelBinderProvider());
this.SetSingle<ModelMetadataProvider>((ModelMetadataProvider) new DataAnnotationsModelMetadataProvider());
this.SetMultiple<ModelValidatorProvider>((ModelValidatorProvider) new DataAnnotationsModelValidatorProvider(), (ModelValidatorProvider) new DataMemberModelValidatorProvider());
this.SetMultiple<ValueProviderFactory>((ValueProviderFactory) new QueryStringValueProviderFactory(), (ValueProviderFactory) new RouteDataValueProviderFactory());
this.SetSingle<IModelValidatorCache>((IModelValidatorCache) new ModelValidatorCache(new Lazy<IEnumerable<ModelValidatorProvider>>((Func<IEnumerable<ModelValidatorProvider>>) (() => ServicesExtensions.GetModelValidatorProviders((ServicesContainer) this)))));
this.SetSingle<IExceptionHandler>((IExceptionHandler) new DefaultExceptionHandler());
this.SetMultiple<IExceptionLogger>();
this._serviceTypesSingle = new HashSet<Type>((IEnumerable<Type>) this._defaultServicesSingle.Keys);
this._serviceTypesMulti = new HashSet<Type>((IEnumerable<Type>) this._defaultServicesMulti.Keys);
this.ResetCache();
}
Ответ 4
Вы можете посмотреть следующий пример из команды Web API:
http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/Elmah/ReadMe.txt