Angular在ASP.NET MVC之上,显示错误

Eri*_*Cal 5 c# asp.net-mvc angularjs

我们在现有的asp.net c#MVC应用程序上放置一个有角度的前端.在我们的服务器代码中,我们可以使用自定义异常来返回商业规则错误.

有没有最好的做法或最简单的方法来处理mvc控制器或webApi控制器上的异常(实际上是从商务层跳出来)并将其转换为角度并在"用户错误"弹出窗口中显示它?人们如何解决这个问题?

Ira*_*chi 5

其他人已经给出了很好的答案,但我想详细阐述我的方法,因为我猜它将涵盖更多细节的两端(前端和服务器).

这是我在WebAPI + AngularJS应用程序中完成错误和异常处理的方法.

步骤1.服务器端的WebApi控制器

我有一个特定的DTO用于向客户端传达验证错误,因为我认为它们与Exceptions 不同.异常将导致500错误,其中验证结果应导致400(错误请求)错误.

所以,这是我的ApiValidationResult课:

public class ApiValidationResult
{
    public List<ApiValidationError> Errors { get; set; }

    public static ApiValidationResult Failure(string errorKey)
    {
        return new ApiValidationResult {Errors = new List<ApiValidationError> {new ApiValidationError(errorKey)}};
    }

    // You can add a bunch of utility methods here
}

public class ApiValidationError
{
    public ApiValidationError()
    {
    }

    public ApiValidationError(string errorKey)
    {
        ErrorKey = errorKey;
    }

    // More utility constructors here

    public string PropertyPath { get; set; }
    public string ErrorKey { get; set; }
    public List<string> ErrorParameters { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我总是使用自己的基类用于WebApi(和MVC)控制器,因此我可以使用它们来添加方便的结果方法,例如:

public abstract class ExtendedApiController : ApiController
{
    protected IHttpActionResult ValidationError(string error)
    {
        return new ValidationErrorResult(ApiValidationResult.Failure(error), this);
    }

    // More utility methods can go here
}
Run Code Online (Sandbox Code Playgroud)

它使用IHttpActionResult我专门为此目的创建的自定义:

public class ValidationErrorResult : NegotiatedContentResult<ApiValidationResult>
{
    public ValidationErrorResult(ApiValidationResult content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters) 
        : base(HttpStatusCode.BadRequest, content, contentNegotiator, request, formatters)
    {
    }

    public ValidationErrorResult(ApiValidationResult content, ApiController controller)
        : base(HttpStatusCode.BadRequest, content, controller)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,我可以在我的控制器操作中干净地使用这样的代码:

    [HttpPost]
    public IHttpActionResult SomeAction(SomeInput input)
    {
        // Do whatever...
        if (resultIsValid)
        {
            return Ok(outputObject);
        }

        return ValidationResult(errorMessage);
    }
Run Code Online (Sandbox Code Playgroud)

步骤2.处理意外异常

正如我所说,我相信只有真正未处理的Exceptions 才会导致500(内部服务器错误)响应.

WebApi会自动将此类未处理的异常转换为500结果.我唯一需要做的就是记录它们.所以,我创建了一个IExceptionLogger接口的实现,并像这样注册:

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new UnhandledExceptionLogger());
Run Code Online (Sandbox Code Playgroud)

步骤3.在客户端拦截并显示错误

AngularJS允许拦截从$http服务发送的所有HTTP调用.我使用它来集中所有消息弹出窗口.这是我的拦截器代码:

appModule.factory("errorsHttpInterceptor", [
    "$q", "$rootScope", "$injector",
    ($q: ng.IQService, $rootScope: IAppRootScopeService, $injector) => {
        return {
            'responseError': rejection => {
                // Maybe put the error in $rootScope and show it in UI
                // Maybe use a popup
                // Maybe use a 'toast'
                var toastr = $injector.get('toastr');
                toastr.error(...);

                return $q.reject(rejection);
            }
        };
    }
]);
Run Code Online (Sandbox Code Playgroud)

您可以在拦截器中执行各种操作,例如记录调试消息,或将键应用于错误代码的显示字符串转换.您还可以区分500到400个错误,并显示不同类型的错误消息.

我使用toastr库,我认为它显示了一个很好的用户界面,并且在API级别非常方便.

最后,我像这样注册拦截器:

appModule.config([
    '$httpProvider',
    ($httpProvider: ng.IHttpProvider) => {
        $httpProvider.interceptors.push('errorsHttpInterceptor');
    }
]);
Run Code Online (Sandbox Code Playgroud)

语法在TypeScript中,与JavaScript非常相似,我相信你可以弄清楚它的含义.