HttpResponseMessage和HttpResponseException有什么区别

时间:2012-05-18 22:56:51

标签: c# asp.net-web-api

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

 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的目的是什么?

5 个答案:

答案 0 :(得分:66)

两者之间的主要区别在于此。该异常对于立即停止处理和退出很有用。例如,假设我有以下代码

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。我正在使用后面的位,但是要求您使用Request的CreateResponse扩展方法。

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

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

希望这有帮助

答案 1 :(得分:28)

当您的Controller Action签名看起来像

时,HttpResponseException非常有用
  Foo Get(int id)

在这种情况下,您无法轻松返回状态代码,如400.

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

答案 2 :(得分:13)

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

在获取Customer的非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);
}

答案 3 :(得分:2)

HttpResponseException派生自Exception并嵌入HttpResponseMessage。 由于它来自Exception,因此在try - catch方案中非常有用。

HttpResponseException返回的默认状态代码为HttpStatusCode.InternalServerError

答案 4 :(得分:0)

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

HttpResponseException的真正目的是允许子方法创建和抛出&#39;他们自己的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,就像动作方法本身一样。