HttpResponseMessage和HttpResponseException有什么区别

cuo*_*gle 57 c# asp.net-web-api

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

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

     throw new HttpResponseException(response);
 }
Run Code Online (Sandbox Code Playgroud)

和:

 public HttpResponseMessage Get()
 {
     return ControllerContext.Request
                        .CreateResponse(HttpStatusCode.BadRequest, "abc");
 }
Run Code Online (Sandbox Code Playgroud)

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

Gle*_*ock 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果此代码运行并且我传递了一个不存在的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;
  }
}
Run Code Online (Sandbox Code Playgroud)

*注意:如果您使用的是beta位,则会创建一个新的HttpResponseMessage.我正在使用后面的位,但是要求您使用Request的CreateResponse扩展方法.

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

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

希望这可以帮助

  • 我对"请求继续处理"的含义感到困惑.请问`return`时请求是否结束? (5认同)
  • 我想补充说,异常处理/日志记录是另一个原因.您可能想要记录404但不抛出而不记录412. (3认同)

Dar*_*ler 28

当您的Controller Action签名如下时,HttpResponseException非常有用

  Foo Get(int id)
Run Code Online (Sandbox Code Playgroud)

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

请注意,HttpResponseMessage<T>Web API的下一版本将会消失.

  • 只有通用的HttpResponseMessage <T>才会消失 (4认同)

Bri*_*nga 13

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

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

public Customer GetCustomer(int id)
{
    return db.Customers.Find(id);
}
Run Code Online (Sandbox Code Playgroud)

但是在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);
}
Run Code Online (Sandbox Code Playgroud)

  • @Brian这是一种风格的东西.有些人希望深入了解HTTP并感觉它是应用程序设计的一部分.其他人认为HTTP是一个实现细节,而宁愿使用ActionFilters和HttpMessageHandlers抽象出HTTP.如果你知道自己在做什么,这两种方法都不对.我倾向于采取你的方法,因为我觉得隐藏HTTP使得事情看起来太像RPC. (5认同)