Browse Source

Improvements on exception handling.

pull/113/head
Halil İbrahim Kalkan 9 years ago
parent
commit
f7a8c8cb14
  1. 103
      src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
  2. 9
      src/Volo.Abp/Volo/Abp/Ui/IUserFriendlyException.cs
  3. 8
      src/Volo.Abp/Volo/Abp/Ui/UserFriendlyException.cs
  4. 2
      src/Volo.Abp/Volo/Abp/Validation/AbpValidationException.cs
  5. 10
      src/Volo.Abp/Volo/Abp/Validation/IHasValidationErrors.cs

103
src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs

@ -27,69 +27,94 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
return errorInfo; return errorInfo;
} }
private RemoteServiceErrorInfo CreateErrorInfoWithoutCode(Exception exception) protected virtual RemoteServiceErrorInfo CreateErrorInfoWithoutCode(Exception exception)
{ {
if (SendAllExceptionsToClients) if (SendAllExceptionsToClients)
{ {
return CreateDetailedErrorInfoFromException(exception); return CreateDetailedErrorInfoFromException(exception);
} }
if (exception is AggregateException && exception.InnerException != null) exception = TryToGetActualException(exception);
if (exception is EntityNotFoundException)
{ {
var aggException = exception as AggregateException; return CreateEntityNotFoundError(exception as EntityNotFoundException);
if (aggException.InnerException is UserFriendlyException ||
aggException.InnerException is AbpValidationException)
{
exception = aggException.InnerException;
}
} }
if (exception is UserFriendlyException) if (exception is AbpAuthorizationException)
{ {
var userFriendlyException = exception as UserFriendlyException; var authorizationException = exception as AbpAuthorizationException;
return new RemoteServiceErrorInfo(userFriendlyException.Message, userFriendlyException.Details); return new RemoteServiceErrorInfo(authorizationException.Message);
} }
if (exception is AbpValidationException) var errorInfo = new RemoteServiceErrorInfo();
if (exception is IUserFriendlyException)
{ {
return new RemoteServiceErrorInfo(L("ValidationError")) var userFriendlyException = exception as IUserFriendlyException;
{ errorInfo.Message = userFriendlyException.Message;
ValidationErrors = GetValidationErrorInfos(exception as AbpValidationException), errorInfo.Details = userFriendlyException.Details;
Details = GetValidationErrorNarrative(exception as AbpValidationException)
};
} }
if (exception is EntityNotFoundException) if (exception is IHasValidationErrors)
{ {
var entityNotFoundException = exception as EntityNotFoundException; if (errorInfo.Message.IsNullOrEmpty())
{
errorInfo.Message = L("ValidationError");
}
if (entityNotFoundException.EntityType != null) if (errorInfo.Details.IsNullOrEmpty())
{ {
return new RemoteServiceErrorInfo( errorInfo.Details = GetValidationErrorNarrative(exception as IHasValidationErrors);
string.Format(
L("EntityNotFound"),
entityNotFoundException.EntityType.Name,
entityNotFoundException.Id
)
);
} }
errorInfo.ValidationErrors = GetValidationErrorInfos(exception as IHasValidationErrors);
}
if (errorInfo.Message.IsNullOrEmpty())
{
errorInfo.Message = L("InternalServerError");
}
return errorInfo;
}
protected virtual RemoteServiceErrorInfo CreateEntityNotFoundError(EntityNotFoundException exception)
{
if (exception.EntityType != null)
{
return new RemoteServiceErrorInfo( return new RemoteServiceErrorInfo(
entityNotFoundException.Message string.Format(
L("EntityNotFound"),
exception.EntityType.Name,
exception.Id
)
); );
} }
if (exception is AbpAuthorizationException) return new RemoteServiceErrorInfo(exception.Message);
}
protected virtual Exception TryToGetActualException(Exception exception)
{
if (exception is AggregateException && exception.InnerException != null)
{ {
var authorizationException = exception as AbpAuthorizationException; var aggException = exception as AggregateException;
return new RemoteServiceErrorInfo(authorizationException.Message);
if (aggException.InnerException is IUserFriendlyException ||
aggException.InnerException is AbpValidationException ||
aggException.InnerException is EntityNotFoundException ||
aggException.InnerException is AbpAuthorizationException)
{
return aggException.InnerException;
}
} }
return new RemoteServiceErrorInfo(L("InternalServerError")); return exception;
} }
private RemoteServiceErrorInfo CreateDetailedErrorInfoFromException(Exception exception) protected virtual RemoteServiceErrorInfo CreateDetailedErrorInfoFromException(Exception exception)
{ {
var detailBuilder = new StringBuilder(); var detailBuilder = new StringBuilder();
@ -105,15 +130,15 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
return errorInfo; return errorInfo;
} }
private void AddExceptionToDetails(Exception exception, StringBuilder detailBuilder) protected virtual void AddExceptionToDetails(Exception exception, StringBuilder detailBuilder)
{ {
//Exception Message //Exception Message
detailBuilder.AppendLine(exception.GetType().Name + ": " + exception.Message); detailBuilder.AppendLine(exception.GetType().Name + ": " + exception.Message);
//Additional info for UserFriendlyException //Additional info for UserFriendlyException
if (exception is UserFriendlyException) if (exception is IUserFriendlyException)
{ {
var userFriendlyException = exception as UserFriendlyException; var userFriendlyException = exception as IUserFriendlyException;
if (!string.IsNullOrEmpty(userFriendlyException.Details)) if (!string.IsNullOrEmpty(userFriendlyException.Details))
{ {
detailBuilder.AppendLine(userFriendlyException.Details); detailBuilder.AppendLine(userFriendlyException.Details);
@ -158,7 +183,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
} }
} }
private RemoteServiceValidationErrorInfo[] GetValidationErrorInfos(AbpValidationException validationException) protected virtual RemoteServiceValidationErrorInfo[] GetValidationErrorInfos(IHasValidationErrors validationException)
{ {
var validationErrorInfos = new List<RemoteServiceValidationErrorInfo>(); var validationErrorInfos = new List<RemoteServiceValidationErrorInfo>();
@ -177,7 +202,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
return validationErrorInfos.ToArray(); return validationErrorInfos.ToArray();
} }
private string GetValidationErrorNarrative(AbpValidationException validationException) protected virtual string GetValidationErrorNarrative(IHasValidationErrors validationException)
{ {
var detailBuilder = new StringBuilder(); var detailBuilder = new StringBuilder();
detailBuilder.AppendLine(L("ValidationNarrativeTitle")); detailBuilder.AppendLine(L("ValidationNarrativeTitle"));
@ -191,7 +216,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
return detailBuilder.ToString(); return detailBuilder.ToString();
} }
private string L(string name) protected virtual string L(string name)
{ {
//TODO: Localization? //TODO: Localization?
//try //try

9
src/Volo.Abp/Volo/Abp/Ui/IUserFriendlyException.cs

@ -0,0 +1,9 @@
namespace Volo.Abp.Ui
{
public interface IUserFriendlyException
{
string Message { get; }
string Details { get; set; }
}
}

8
src/Volo.Abp/Volo/Abp/Ui/UserFriendlyException.cs

@ -9,12 +9,12 @@ namespace Volo.Abp.Ui
/// This exception type is directly shown to the user. /// This exception type is directly shown to the user.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class UserFriendlyException : AbpException, IHasLogLevel, IHasErrorCode public class UserFriendlyException : AbpException, IHasLogLevel, IHasErrorCode, IUserFriendlyException
{ {
/// <summary> /// <summary>
/// Additional information about the exception. /// Additional information about the exception.
/// </summary> /// </summary>
public string Details { get; private set; } public string Details { get; set; }
/// <summary> /// <summary>
/// An arbitrary error code. /// An arbitrary error code.
@ -41,7 +41,7 @@ namespace Volo.Abp.Ui
public UserFriendlyException(SerializationInfo serializationInfo, StreamingContext context) public UserFriendlyException(SerializationInfo serializationInfo, StreamingContext context)
: base(serializationInfo, context) : base(serializationInfo, context)
{ {
} }
/// <summary> /// <summary>
@ -58,7 +58,7 @@ namespace Volo.Abp.Ui
/// Constructor. /// Constructor.
/// </summary> /// </summary>
/// <param name="message">Exception message</param> /// <param name="message">Exception message</param>
/// <param name="severity">Exception severity</param> /// <param name="logLevel">Exception severity</param>
public UserFriendlyException(string message, LogLevel logLevel) public UserFriendlyException(string message, LogLevel logLevel)
: base(message) : base(message)
{ {

2
src/Volo.Abp/Volo/Abp/Validation/AbpValidationException.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Validation
/// This exception type is used to throws validation exceptions. /// This exception type is used to throws validation exceptions.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class AbpValidationException : AbpException, IHasLogLevel public class AbpValidationException : AbpException, IHasLogLevel, IHasValidationErrors
{ {
/// <summary> /// <summary>
/// Detailed list of validation errors for this exception. /// Detailed list of validation errors for this exception.

10
src/Volo.Abp/Volo/Abp/Validation/IHasValidationErrors.cs

@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Volo.Abp.Validation
{
public interface IHasValidationErrors
{
IList<ValidationResult> ValidationErrors { get; set; }
}
}
Loading…
Cancel
Save