我是伊只雄熊

导航

ASP.NET Web API 异常处理 HttpResponseException 以及Angularjs获取异常信息并提示

一、HttpResponseException

  如果一个Web API控制器抛出一个未捕捉异常,默认地,大多数异常都会被转化成一个带有状态码“500 – 内部服务器错误”的HTTP响应。HttpResponseException(HTTP响应异常)类型会返回你在异常构造器中指定的任何HTTP状态码。例如,在以下方法中,如果id参数非法,会返回“404 — 未找到”。

public Product GetProduct(int id) 
{ 
    Product item = repository.Get(id); 
    if (item == null) 
    { 
     //指定响应状态码
throw new HttpResponseException(HttpStatusCode.NotFound); } return item; }

  为了对响应进行更多控制,你也可以构造整个响应消息HttpResponseMessage,并用HttpResponseException来包含它:

public Product GetProduct(int id) 
{ 
    Product item = repository.Get(id); 
    if (item == null) 
    { 
        var resp = new HttpResponseMessage(HttpStatusCode.NotFound) 
        { 
            Content = new StringContent(string.Format("No product with ID = {0}", id)), 
            ReasonPhrase = "Product ID Not Found" 
        } 
     //包含一个HttpResponseMessage
throw new HttpResponseException(resp); } return item; }

二、Exception Filters

  继承ExceptionFilterAttribute,重写OnException,最后都是抛出HttpResponseException,包含一个HttpResponseMessage,调用客户端可以获取该异常信息,进行相应处理。

 public class ExceptionHandlingAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception != null && !(context.Exception is HttpResponseException))
            {
                MetricsConfig.MarkException(context.Exception);

                if (context.Exception is UnauthorizedAccessException)
                {
                    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized));
                }

                var exceptionData = new ExceptionData
                {
                    Name = context.Exception.GetType().Name,
                    Message = context.Exception.GetBaseException().Message
                };

                if (context.Exception is ApplicationException)
                {
                    exceptionData.Message = context.Exception.Message;
                    var businessException = context.Exception as CustomBusinessException;
                    if (businessException != null)
                    {
                        exceptionData.Data = businessException.Data;
                    }
                }

                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    Content = new ObjectContent<ExceptionData>(exceptionData, JsonFormatter),
                    ReasonPhrase = context.Exception.GetType().Name
                });

            }
        }

        private JsonMediaTypeFormatter _JsonFormatter;
        private JsonMediaTypeFormatter JsonFormatter
        {
            get
            {
                if (_JsonFormatter == null)
                {
                    _JsonFormatter = new JsonMediaTypeFormatter();
                    _JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                }
                return _JsonFormatter;
            }
        }

        // A simple class for generate response with json content.
        public class ExceptionData
        {
            public string Name { get; set; }
            public string Message { get; set; }
            public string Data { get; set; }
        }
    }

  注册:

  以下是全局注册,当然也可以在Controller或Action上标注

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
           
            // register exception handler.
            config.Filters.Add(new ExceptionHandlingAttribute());

        }
    }

三、客户端获取异常

  通过AngularJs中AOP拦截响应实现

// apiInterceptor is responsible to handle the aspect of each request and response.
webservices.factory('apiInterceptor',
['$q', '$log', '$injector', 'loginContext', 'eventAggregator', function ($q, $log, $injector, loginContext, eventAggregator) {
    'use strict';

    var apiToken = loginContext.apiToken;
    var tokenType = loginContext.tokenType;
    var webApiHostUrl = loginContext.apiHost + "/api/v1";

    return {
        //token save to services for further usage
        tokenType: tokenType,
        apiToken: apiToken,
        webApiHostUrl: webApiHostUrl,

        // On request success 请求拦截
        request: function (config) {
            if (config.isWebApiRequest && !config.isPlugin) {
          //地址上都自动附加上/api/v1 config.url
= (config.mkApiUrl || webApiHostUrl) + config.url; config.headers = config.headers || {};
          //添加Authorization,用tokeentype token格式来定义 ,如 ‘bearer sfsfsfsfsdf=sfsf+...’
config.headers.Authorization
= tokenType + ' ' + (config.mkToken || apiToken); var specificOfficeId = Ares.specificOfficeUtil.getOfficeId(); if (specificOfficeId) { config.headers["specific-office-id"] = specificOfficeId; } } else if (config.handleApiRequest) { config = config.handleApiRequest(config); } return config; }, // On request failure requestError: function (rejection) { $log.error(rejection); // Contains the data about the error on the request. // Return the promise rejection. return $q.reject(rejection); }, // On response failture,响应拦截 responseError: function (response) { $log.error(response); // Contains the data about the error. if (response.status === 401) {//状态码判断 //window.location = '/logoff'; Ares.logOff(); } else if (response.data) {//返回内容判断 if (response.data.name == 'TenantInactiveException') { aresMaintainUtil.goToTenantInactivePage(); }
          //发布一个订阅,导致弹出一个对话框 eventAggregator.publish(eventAggregator.events.ApiErrorHappened, response,
'apiInterceptor'); } else if (response.status === 0) { var isSaasApi = true; if (response.config && response.config.url.indexOf('//marketcenter') > -1) { isSaasApi = false; } if (isSaasApi) { aresMaintainUtil.ensureInMaintainMode().then(function (isInMaintainMode) { if (isInMaintainMode) { aresMaintainUtil.goToMaintainPage(); } }); } } // Return the promise rejection. return $q.reject(response); } }; }]); //Aop拦截,对响应 webservices.config(['$httpProvider', function ($httpProvider) { $httpProvider.interceptors.push('apiInterceptor'); }]);

  注册订阅:

var subscribeEvents = function () {
        eventAggregator.subscribe($scope, eventAggregator.events.ApiErrorHappened, onApiErrorHappened);
    };

    //弹出提示对话框
    var onApiErrorHappened = function (event, args) {
        if (args.data.name == 'MyOperationException'
                || args.data.name == 'CustomBusinessException') {
            customDialog.info('系统提示', args.data.message);
        }
    };

 

posted on 2018-02-07 10:48  我是伊只雄熊  阅读(4427)  评论(1编辑  收藏  举报