【问题标题】:Throwing validation errors from Web API从 Web API 引发验证错误
【发布时间】:2016-11-12 11:13:06
【问题描述】:

我正在用 C# 编写 web api,尝试遵循 REST 概念,即成功响应将是 HttpStatus: 200,验证错误将是 433 等等。

我在 global.asax 中为整个应用程序注册了 ExceptionFilter。

我的问题是,对于身份验证期间的验证错误,如果身份验证失败,那么应该如何将消息传回给客户端(它必须是不同的状态代码,例如 433 或 401)。

到目前为止,我正在从业务层抛出自定义异常。是否建议出现错误时抛出异常?

以下是代码示例:

记录器

public class ExceptionFilter : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        HttpResponseMessage response;
        if (context.Exception is ExceptionBase)
        {
            response = context.Request.CreateResponse(HttpStatusCode.InternalServerError,
                new ErrorDTO() { ErrorCode = (int)((ExceptionBase)context.Exception).ExceptionCode, Messages = ((ExceptionBase)context.Exception).Message });
        }
        else {
            response = context.Request.CreateResponse(HttpStatusCode.InternalServerError,
                new ErrorDTO() { ErrorCode = (int)HttpStatusCode.InternalServerError, Messages = "Error occured at server." });
        }
        context.Response = response;
        base.OnException(context);
        LogException(context);
    }

    private static void LogException(HttpActionExecutedContext context)
    {
        if (context.Exception != null)
        {
            Logger.Instance.LogError(context.ActionContext.ActionDescriptor.ActionName, context.Exception);
        }
    }

    public override Task OnExceptionAsync(HttpActionExecutedContext context, CancellationToken cancellationToken)
    {
        return base.OnExceptionAsync(context, cancellationToken);
    }
}

业务层

public AuthorizationTokenDTO AuthenticateUser(UserDTO userDTO)
{
    User userEntity = _userRepository.GetUserWithAssociatedRole(userDTO.UserName);

    if (userEntity == null)
        throw new BLException("User does not exists.", ExceptionCode.RestApiValidation);

    ActiveDirectory activeDirectory = _activeDirectoryRepository.GetEntityById(ConfigurationSettings.GetConfigSetting<int>(ApplicationConstants.ActiveDirectoryId));

    if (activeDirectory == null)
        throw new BLException("UserName or password is incorrect.", ExceptionCode.RestApiValidation);

    using (var context = new PrincipalContext(ContextType.Domain))
    {
        string password = EncryptionUtility.Decrypt(userDTO.Password, ConfigurationSettings.GetConfigSetting<string>(ApplicationConstants.PrivateKeyForRSAEncryption));

        if (!context.ValidateCredentials(userDTO.UserName, password))
            throw new BLException("UserName or password is incorrect.", ExceptionCode.RestApiValidation);

        UserAccessTokenDTO accessToken = GenrateNewUserAccessToken(userEntity);

        if (accessToken == null)
            throw new BLException("Error occured while generating access token.", ExceptionCode.RestApiValidation);

        return GetAuthorizationTokenDTO(userEntity, accessToken);
    }
}

是否建议在这种情况下抛出异常?还是有更好的方法来编写 Web API?

【问题讨论】:

    标签: c# rest asp.net-web-api error-handling


    【解决方案1】:

    ExceptionFilter 应该只捕获“未处理”的异常,可以这么说。您可以将这些异常保留在 BusinessLayer 中并在控制器中捕获它们,或者返回某种对象。然后只需从控制器返回带有适当 HttpStatusCode 的响应。

    或者,您可以将您的响应包装到也知道 HttpStatusCode(和错误消息)的内容中。

    【讨论】:

    • 感谢您的回复。这些服务将由 WPF 客户端使用。如果我使用请求/响应模型来访问rest api,那么rest apis将始终返回httpstatuscode 200,我们最终将在代码中有很多if/else条件(检查天气响应是成功还是失败) .所以我打算如何做到这一点,在 WPF 中捕获这些 http 异常,在 WPF 应用程序类中将捕获这些异常(http 异常)并将消息发送到活动视图(通过事件聚合器),让视图处理来自休息的异常api
    • 这样我们只在代码必须失败的地方编写成功和失败的代码,而不会影响实际的代码流。即错误场景将被错误流覆盖,真正的代码只关心所需的业务。
    猜你喜欢
    • 1970-01-01
    • 2013-11-18
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2014-03-19
    • 2020-09-21
    相关资源
    最近更新 更多