Asp.Net WebApi捕获控制器构造函数中生成的异常

时间:2018-01-09 21:43:07

标签: c# asp.net-web-api active-directory windows-authentication

在我的基本API控制器类构造函数中,我基于Windows身份验证填充用户权限。我正在使用像

这样的东西
    var ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName.ToUpper());
    var userInfo = UserPrincipal.FindByIdentity(ctx, System.Environment.UserName.ToUpper());

从AD获取用户信息。问题是,当用户被锁定时,应用程序失败,因为构造函数中发生异常。有没有办法处理这些调用的异常并将其冒泡为未经授权的异常或其他?我尝试用try catch包围它并且在未经授权的情况下抛出httpresponse异常,但它仍然冒泡为500。

编辑#1

构造函数中发生了更多的事情,当它失败时我不想失败500.我需要捕获异常并抛出其他东西。授权只是其中一件事的一个例子。

编辑#2

对于所有写作的人我不应该在构造函数中有任何逻辑:

构造函数用于将对象初始化为有效状态。应用程序的这一部分的控制器必须具有数据库连接,用户信息和一些其他属性,因为所有请求都使用了所有这些信息。如果其中任何一个失败,我想向用户返回不同类型的错误。在标准类的情况下,它将是不同类型的异常(SqlException,DbConnectionException,某种AD异常)。在WebApi的情况下,我希望它是一种不同类型的响应代码(未授权,未实现(501)等)。将相同代码复制粘贴到应用程序该部分中的每个请求都表示存在维护问题。

2 个答案:

答案 0 :(得分:0)

由于原始异常几次被包装到其他异常中,我到目前为止找到的唯一方法是使用全局异常过滤器,然后浏览上下文的内部异常。例外,直到它为空或我没有达到我正在寻找的类型的例外。

<script>
var dayOne = `Welcome
Home
Contact
Info
A
Andy 29 5'9 $3000 low
B
Betty 19 4'8 $2800 low
Bella 23 5'2 £4300 medium
C
Charles 43 5'3 $5000 high
Your local date/time is Thu Jan 11 2018 20:58:14 GMT+0000 (GMT Standard Time).
Current server date/time is 11-01-2018 | 21:58 
Logout `;

var dayTwo = `

Welcome
Home
Contact
Info
A
Andy 29 5'9 $3200 low
B
Betty 19 4'8 $2900 low
Bella 23 5'2 £3900 high
C
Charles 43 5'3 $7000 high
Carrie 18 5'8 $1000 medium
Your local date/time is Thu Jan 11 2018 20:58:14 GMT+0000 (GMT Standard Time).
Current server date/time is 11-01-2018 | 21:58 
Logout `;

/**
* Converts an array to an object with keys for later comparison
*/
function convertNamesToKeys(arr){
    var obj = {}
    for(var i=0, j=arr.length; i<j; i+=1){
        var name = arr[i].substring(0,arr[i].indexOf(' '));
        obj[name] = arr[i];
    }
    return obj;
}

/**
* Count object length
*/
function getObjectLength(obj) {
    var length = 0;
    for( var key in obj ) {
        if( obj.hasOwnProperty(key) ) {
            length+=1;
        }
    }
    return length;
};


/**
* Compares two objects for differences in values
* retains objects with different keys
*/
function compareObjectValue(primaryObject, secondaryObject){

    for(var name in primaryObject){
        if( primaryObject.hasOwnProperty(name) 
            && name in secondaryObject){

            if(primaryObject[name] === secondaryObject[name]){
                delete primaryObject[name];
            }
        }
    }

    //This is your final array which should contain just unique values between the two days
    console.log(primaryObject);

}
//split the large string into lines for manageability and simplicity of regex
var dayOneArray = dayOne.match(/[^\r\n]+/g);
var dayTwoArray = dayTwo.match(/[^\r\n]+/g);

//discard any lines which are noise
var regex = /^[a-z\s0-9']+(\$|£)[0-9\sa-z]+$/i
var dayOneFiltered = dayOneArray.filter(line => regex.test(line));
var dayTwoFiltered = dayTwoArray.filter(line => regex.test(line));

//convert the arrays into objects using name as key for easy comparison
var dayOneConverted = convertNamesToKeys(dayOneFiltered);
var dayTwoConverted = convertNamesToKeys(dayTwoFiltered);

//Determine which of the two objects is the larger and loop that one
//We will unset keys which have values that are the same and leave keys 
//in the larger array which must be unique - not sure if you want that?
if( getObjectLength(dayOneConverted) > getObjectLength(dayTwoConverted)){
    compareObjectValue(dayOneConverted, dayTwoConverted)
}
else {
    compareObjectValue(dayTwoConverted, dayOneConverted);
}

</script>

接下来我需要在WebApiConfig.Register中注册它:

namespace SomeWebApi
{
    public class GlobalExceptionHandler : ExceptionHandler
    {
        public override async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
        {
            if (context.Exception != null)
            {
                Exception filteredException = context.Exception;

                while (
                    (filteredException != null)
                    &&
                    (filteredException.GetType() != typeof(HttpResponseException)
                )
                {
                    filteredException = filteredException.InnerException ;
                }

                if (
                    (filteredException != null)
                    &&
                    (filteredException != context.Exception)
                )
                {
                    var httpResponseException = (HttpResponseException) filteredException;
                    var response = context.Request.CreateErrorResponse(
                        httpResponseException.Response.StatusCode,
                        httpResponseException
                    );

                    context.Result = new ResponseMessageResult(response);
                }
            }
        }
    }
}

答案 1 :(得分:-1)

最流行的方法是不在控制器构造函数中使用user / sesion相关逻辑。 对于身份验证您可以使用属性过滤器,为了创建用户信息,只需创建帮助程序类并在需要时使用它。

修改

最后一件事:尝试使用依赖注入(如结构图)它将强制您在构造函数中进行适当的更改,这将使初始化更容易。 https://www.exceptionnotfound.net/setting-up-dependency-injection-in-web-api-with-structuremap/