Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 位于ASP.NET MVC顶部,显示错误_C#_Asp.net Mvc_Angularjs - Fatal编程技术网

C# 位于ASP.NET MVC顶部,显示错误

C# 位于ASP.NET MVC顶部,显示错误,c#,asp.net-mvc,angularjs,C#,Asp.net Mvc,Angularjs,我们正在现有的asp.net c#MVC应用程序上安装一个角度前端。在服务器代码中,我们广泛使用自定义异常来返回业务规则错误 有没有最佳实践或最灵活的方法来处理mvc控制器或webApi控制器上的异常(实际上是从业务层弹出的),并将其传递到angular并在“用户错误”弹出窗口中显示?人们是如何解决这个问题的?通常,我一直在我们的WEB API中做这类事情,返回正确的状态代码是关键,当然,对于您想要使用的许多前端框架中的哪一个,这是完全不可知的 public IHttpActionResult

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


有没有最佳实践或最灵活的方法来处理mvc控制器或webApi控制器上的异常(实际上是从业务层弹出的),并将其传递到angular并在“用户错误”弹出窗口中显示?人们是如何解决这个问题的?

通常,我一直在我们的WEB API中做这类事情,返回正确的状态代码是关键,当然,对于您想要使用的许多前端框架中的哪一个,这是完全不可知的

public IHttpActionResult Get(DateTime? updatesAfter = null)
        {
            try
            {
                // Do something here.
                return this.Ok(result);
            }
            catch (Exception ex) // Be more specific if you like...
            {
                return this.InternalServerError(ex);
                throw;
            }
        }
现在随WebAPIv2ApicController提供的帮助器方法非常好

this.BadRequest()
this.InternalServerError()
this.Ok()
this.Unauthorized()
this.StatusCode()
this.NotFound()
其中一些(如InternalServerError)允许您将异常或消息(或仅仅是对象)作为参数传递


通常,与任何前端框架或库一样,在初始化对API方法的ajax调用时,您可以提供一个失败或错误回调,在返回错误状态代码的情况下,将调用该回调。

对于我的API控制器,我返回
HttpResponseMessage
。请看我下面的例子。我希望这有帮助

在响应消息中,您还可以将对象传回前端

WEB API

    // Get all
    [HttpGet]
    public HttpResponseMessage Get()
    {
        try
        {
            return Request.CreateResponse(HttpStatusCode.OK, myObject);
        }
        catch (Exception e)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Error Message");
        }
    }
角度JS

// Get Request on Page Load
    $http({
        url: '/api/department/',
        method: 'GET',
    }).success(function (data) {
        $scope.departments = data;
    }).error(function (error) {
        $scope.error = error;
    });
HTML

<div class="alert alert-danger animate-show" role="alert" ng-show="error != null">{{ error }} </div>
<div class="alert alert-success animate-show" role="alert" ng-show="success != null">{{ success }}</div>
{{error}
{{success}}

我们刚刚完成了一个带有角度前端的大型MVC应用程序

我们只是让错误流动,例如任何网页只是得到一个错误,但没有堆栈跟踪(不是黄色屏幕,尼斯错误有***,但在你的主页等)

Web API调用只返回正确的HTTP状态。如果您愿意,它们可以包括一些细节

但是,您不想丢失这些错误,所以我们只安装了带有

Install-Package elmah 
而且,它只是起作用,错误只会出现在日志中,用户会被告知某些东西不起作用等等。。不需要额外的工作

为了使我们的UI更好,我们做了以下几点,例如

未处理的错误

MVC页面

只要让MVC前端完成它的工作,它就会以一种很好的方式告诉用户出了什么问题

角度web调用

在.error函数中,向用户发出警报,例如

}).error(function (data, status, headers, config) {
$scope.addAlert('danger', 'Error deleting autosave details');
}
如果您不希望由于覆盖错误而丢失错误,请让错误堆叠。addAlert只写入前端绑定到的数据数组

已处理错误 如果您正在处理它们,那么您已经管理了发生的事情,但是要记录这些

MVC

如果您只想记录它们,
elmah
API对此有一个调用

ErrorSignal.FromCurrentContext().Raise(exception );
如果您使用的是错误属性,则可以使用此属性

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ElmahHandledErrorLoggerFilter());
        filters.Add(new HandleErrorAttribute());
    }
}

public class ElmahHandledErrorLoggerFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        // Log only handled exceptions, because all other will be caught by ELMAH anyway.
        if (context.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(context.Exception);
    }
}

另外,对于ELMAH框架签出的一般日志记录,其他人已经给出了很好的答案,但我想详细介绍一下我的方法,因为我想它将用更多细节覆盖两端(前端和服务器)

下面是我在WebAPI+AngularJS应用程序中处理错误和异常的完整方法

第一步。服务器端的WebApi控制器 我有一个特定的DTO,用于向客户机传达验证错误,因为我认为它们不同于
Exception
s。异常将导致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; }
}
它使用我专门为此创建的自定义
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)
    {
    }
}
第二步。处理意外异常 正如我所说的,我认为只有真正的未处理的
异常
s才会导致500(内部服务器错误)响应

此类未经处理的异常由WebApi自动转换为500结果。我唯一需要做的就是把它们记录下来。因此,我创建了一个
IEExceptionLogger
接口的实现,并按如下方式注册它:

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new UnhandledExceptionLogger());
appModule.config([
    '$httpProvider',
    ($httpProvider: ng.IHttpProvider) => {
        $httpProvider.interceptors.push('errorsHttpInterceptor');
    }
]);
$http({ method: methodType, url: endpoint })
     .then(function (response) {
          response.status; //gets you the HttpStatusCode to play with
          response.data; //gets you the ReponseContent section
     }, function (response) {
          response.status; //gets you the HttpStatusCode
          response.data; //gets you the ReponseContent section
     });
第三步。在客户端截取并显示错误 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);
            }
        };
    }
]);
您可以在拦截器中执行各种操作,例如记录调试消息,或应用键显示错误代码的字符串转换。您还可以区分500和400个错误,并显示不同类型的错误消息

我使用toastr库,我认为它显示了一个很好的UI,在API级别非常方便

最后,我注册拦截器如下:

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new UnhandledExceptionLogger());
appModule.config([
    '$httpProvider',
    ($httpProvider: ng.IHttpProvider) => {
        $httpProvider.interceptors.push('errorsHttpInterceptor');
    }
]);
$http({ method: methodType, url: endpoint })
     .then(function (response) {
          response.status; //gets you the HttpStatusCode to play with
          response.data; //gets you the ReponseContent section
     }, function (response) {
          response.status; //gets you the HttpStatusCode
          response.data; //gets you the ReponseContent section
     });

语法是用TypeScript编写的,它与JavaScript非常相似,我相信您可以理解它的含义。

另一种方法是返回内容

以下是我如何做到这一点(端到端)。从我的API:

return Content(HttpStatusCode.<statuscode>, "ResponseContent: " + "my_custom_error");
有关HttpStatusCodes的更多详细信息,请参阅

在角度代码中,我是这样读的:

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new UnhandledExceptionLogger());
appModule.config([
    '$httpProvider',
    ($httpProvider: ng.IHttpProvider) => {
        $httpProvider.interceptors.push('errorsHttpInterceptor');
    }
]);
$http({ method: methodType, url: endpoint })
     .then(function (response) {
          response.status; //gets you the HttpStatusCode to play with
          response.data; //gets you the ReponseContent section
     }, function (response) {
          response.status; //gets you the HttpStatusCode
          response.data; //gets you the ReponseContent section
     });
确保在进行http调用时,
responseType
未设置为“JSON”。因为API返回的数据在此阶段不是JSON格式

从中,响应对象具有以下属性:

数据{string | Object}–使用 变换函数

状态–{number}–响应的HTTP状态代码

headers–{function([headerName])}–Header getter函数

config–{Object}–用于 生成请求

statusText–{string}–响应的HTTP状态文本


因为这不是特定于代码的,所以最好在程序员堆栈中使用ExchangeOuter,而黄色死亡屏幕的替代方案是带有抱歉消息的javascript警报。这是个例外,不应该发生,所以我们认为没关系。但是标准错误是根据情况来处理的。感谢您的回复,在Angular si上如何处理这些错误