| 一、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);
        }
    };   |