首页 > 解决方案 > 如何在 ServiceStack 中返回不同的 Http 状态码

问题描述

嗨,我是 Service Stack 的新手,想知道如何返回不同的 http 状态代码。

我需要能够返回的是:

  1. 204 - 已处理但没有内容
  2. 400 - 错误的请求
  3. 404 - 未找到
  4. 422 - 用于验证问题
  5. 500内部服务器错误

任何人都可以帮忙吗?

标签: c#servicestack

解决方案


如果你的 Service 没有返回响应,例如有一个void方法或者返回null,ServiceStack 会自动返回一个204 No Content响应状态。

可以通过以下方式将此行为恢复为空的200 OK响应:

SetConfig(new HostConfig {
    Return204NoContentForEmptyResponse = false
});

返回空响应的请求 DTO 应实现IReturnVoid标记接口

自定义错误代码

所有其他状态代码都是错误状态代码,记录在 ServiceStack 的错误处理文档中。

例如,通常建议返回理想的 C#Exception并让 ServiceStack 自动返回理想的 HTTP 错误代码。

默认情况下,C# 异常继承自:

  • ArgumentExceptionSerializationExceptionFormatException返回400 BadRequest
  • NotImplementedExceptionNotSupportedException返回405 MethodNotAllowed
  • FileNotFoundException返回为404 NotFound
  • AuthenticationException返回为401 Unauthorized
  • UnauthorizedAccessException返回为403 Forbidden
  • OptimisticConcurrencyException返回为409 冲突
  • 所有其他正常的 C# 异常都返回为500 InternalServerError

ArgumentException因此,任何包含大多数Fluent Validation Exceptions的Exceptions 继承都会自动返回首选的400 BadRequest

其他自定义 HTTP 错误状态的方法包括:

C# 异常到 HTTP 错误状态的自定义映射

您可以通过配置它们来更改为不同异常类型返回的 HTTP 错误状态:

SetConfig(new HostConfig { 
    MapExceptionToStatusCode = {
        { typeof(CustomUnprocessableEntityException), 422 },
        { typeof(CustomerNotFoundException), 404 },
    }
});

实现 IHasStatusCode

除了使用 IResponseStatusConvertible自定义 C# 异常的 HTTP 响应正文之外,您还可以通过实现自定义 HTTP 状态代码IHasStatusCode

public class Custom401Exception : Exception, IHasStatusCode
{
    public int StatusCode => 401;
}

返回一个 HttpError

如果您想要更精细地控制 HTTP 错误,您可以抛出返回HttpError让您自定义Http 标头状态代码以及 HTTP 响应正文,以准确获取您想要的内容:

public object Get(User request) 
{
    throw HttpError.NotFound($"User {request.Name} does not exist");
}

以上在线路上返回404 NotFound StatusCode 并且是以下内容的简写:

new HttpError(HttpStatusCode.NotFound, $"User {request.Name} does not exist");

带有自定义响应 DTO 的 HttpError

HttpError还可用于返回更结构化的错误响应:

var responseDto = new ErrorResponse { 
    ResponseStatus = new ResponseStatus {
        ErrorCode = typeof(ArgumentException).Name,
        Message = "Invalid Request",
        Errors = new List<ResponseError> {
            new ResponseError {
                ErrorCode = "NotEmpty",
                FieldName = "Company",
                Message = "'Company' should not be empty."
            }
        }
    }
};

throw new HttpError(HttpStatusCode.BadRequest, "ArgumentException") {
    Response = responseDto,
}; 

推荐阅读