58

我试图理解两者并编写示例代码:

 public HttpResponseMessage Get()
 {
     var response = ControllerContext.Request
                         .CreateResponse(HttpStatusCode.BadRequest, "abc");

     throw new HttpResponseException(response);
 }

和:

 public HttpResponseMessage Get()
 {
     return ControllerContext.Request
                        .CreateResponse(HttpStatusCode.BadRequest, "abc");
 }

从小提琴,我真的没有看到它们之间有什么区别,那么使用的目的是HttpResponseException什么?

4

5 回答 5

67

两者的主要区别在于这一点。该异常对于立即停止处理并退出很有用。例如假设我有以下代码

public class CustomerController : ApiController {
  private ICustomerContext repo;

  public CustomerController(ICustomerContext repo) {
    this.repo = repo;
  }

  public Customer Get(int id) {
    var customer = repo.Customers.SingleOrDefault(c=>c.CustomerID == id);
    if (customer == null) {
      throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
    }
    return customer;
  }
}

如果此代码运行并且我传递了一个不存在的 id,它将立即停止处理并返回状态代码 404。

相反,如果我返回 HttpResponseMessage,请求将愉快地继续其其余处理并返回 404。主要区别在于是否结束请求。

正如 Darrel 所说,在某些情况下我希望继续处理(如找到客户时)而在其他情况下我不想继续处理时,异常很有用。

您可能想要使用类似 HttpResponseMessage 的地方是在 Http POST 中返回状态代码 201 并设置位置标头。在这种情况下,我确实希望继续处理。这将与此代码有关。*

public class CustomerController : ApiController {
  private ICustomerContext repo;

  public CustomerController(ICustomerContext repo) {
    this.repo = repo;
  }

  public HttpResponseMessage Post(Customer customer) {
    repo.Add(customer);
    repo.SaveChanges();
    var response = Request.CreateResponse(HttpStatusCode.Created, customer);
    response.Headers.Location = new Uri(Request.RequestUri, string.format("customer/{0}", customer.id));
    return response;
  }
}

*注意:如果您使用的是 beta 位,您将创建一个新的 HttpResponseMessage。我正在使用后面的位,但是这要求您使用请求之外的 CreateResponse 扩展方法。

上面,我正在创建一个响应,它将状态代码设置为 201,传入客户,然后设置位置标头。

然后返回响应并继续处理请求。

希望这可以帮助

于 2012-05-24T09:18:00.877 回答
28

当您的控制器操作签名看起来像时,HttpResponseException 很有用

  Foo Get(int id)

在这种情况下,您不能轻易返回 400 之类的状态码。

请注意,这HttpResponseMessage<T>将在 Web API 的下一个版本中消失。

于 2012-05-19T03:41:37.387 回答
13

假设您想对响应进行单元测试,那么总是返回 HttpResponseMessage 是否有意义?我不是特别喜欢从 ApiController 返回直接类型的想法,因为它不遵循典型的开发模式。

在获取客户的非 Web API 类中,您可能会返回 null,而您的调用代码会检查 null 响应:

public Customer GetCustomer(int id)
{
    return db.Customers.Find(id);
}

但是在 Web API 中,你不会返回 null,你必须返回一些东西,即使那个东西是在你抛出 HttpResponseException 之后创建的。在这种情况下,为了简化测试,为什么不总是返回一个 HttpResponseMessage,并把它作为你的签名呢?

public HttpResponseMessage GetCustomer(int id)
{
    var customer = db.Customers.Find(id);
    if (customer == null)
    {
        return Request.CreateResponse(HttpStatusCode.NotFound);
    }

    return Request.CreateResponse(HttpStatusCode.OK, customer);
}
于 2012-06-07T14:52:35.957 回答
2

HttpResponseException源自Exception并嵌入HttpResponseMessage. 因为它派生自它在场景中Exception可能很有用。trycatch

返回的默认状态码HttpResponseExceptionHttpStatusCode.InternalServerError

于 2012-05-19T03:27:25.030 回答
0

正如原始问题所述,返回的响应没有真正的区别。

HttpResponseException 的真正目的是允许子方法创建和“抛出”它们自己的 HttpResponseMessages,这些 HttpResponseMessages 流回调用堆栈并返回给客户端。

public class CustomerController : ApiController {
  private ICustomerContext repo;
  public CustomerController(ICustomerContext repo) {
    this.repo = repo;
  }

  public HttpResponseMessage Get(int id) {

    Customer customer = getCustomer(id);

    return Request.CreateResponse(customer);
  }

  private Customer getCustomer(int id){
    .....do some work
    .....we have a problem so throw exception
    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest, "Id out of range");
    return repo.Customers.SingleOrDefault(c=>c.CustomerID == id)
}

原谅任何错误,即时编写的代码。抛出的 HttpResponseException 通过动作调用堆栈冒泡,不会被正常的异常处理程序捕获并返回其 HttpResponseMessage 就像动作方法本身一样。

于 2014-08-20T20:12:33.260 回答