ASP.NET Web API - 返回CLR对象还是HttpResponseMessage

16

在Web API中,从动作方法返回的类型通常是什么?

像这样返回CLR对象:

public IEnumerable<ContactModel> Get()
{
    return _contactService.GetAllForUser();
}

或者将您的对象包装在一个HttpResponseMessage中:

public HttpResponseMessage Get()
{
    IEnumerable<ContactModel> contacts = _contactService.GetAllForUser();

    return Request.CreateResponse((HttpStatusCode) 200, contacts);
}

我更喜欢将自己的CLR对象作为返回类型,因为这显然会导致更清晰的方法,因为您不必每次都进行HttpResponseMessage实例化。


据我所知,如果你返回了CRL类型,在异常情况下,异常消息会传播到客户端,这并不是一个好的实践。 - Furqan Hameedi
显然不是这样的,但看看@Claudio的回答,他建议您可以捕获异常并使用HttpResponseException返回适当的响应给客户端。 - jcvandan
2个回答

18
重要的一点是这个选择是偏好问题。如果你正在创建一个“URI-Style”的HTTP API,其中返回类型由客户端预先知道,那么这可能是你首选的方法。
然而,就我个人而言,我不喜欢返回CLR类型。我认为采取这种方法会使你失去HTTP的许多好处。我总是返回HttpResponseMessage。
如果考虑标准的过程调用,有两种可能的结果,你会得到返回类型或者异常。由于重定向、暂时不可用的服务器、无内容、未修改、服务器协商、首选头变量等原因,HTTP交互比这更加灵活多样。
我认为ApiController类是应用程序将面向对象的方法调用映射到HTTP请求/响应的地方。我认为明确进行这种映射有助于利用HTTP。让框架神奇地将CLR类型转换为某种线路表示形式,虽然节省了一些打字,但却模糊了正在发生的事情,并迫使您间接地通过ActionFilters和MessageHandlers执行任何类型的HTTP交互。
我不想说服那些更喜欢返回CLR类型的人改变,我只想向那些喜欢返回HttpResponseMessage的人保证,尽管你看不到很多这样的示例,但这是完全可行的选择。

2
使用HttpResponseMessage的一个好处是,如果出现错误请求或服务器错误,可以返回“错误类型”,而不必尝试将错误附加到空的CLR对象上,因为您被绑定到特定的返回类型。+1 - Josh Noe
我刚刚创建了一个通用的ReturnMessages类,它具有一个ReturnClass值,该值保存CLR对象。此类还具有返回代码、返回消息和任何相关数据(以防发生意外事件)。这样,我可以为所有消息返回相同的类,然后在消费时检查类型。 - user3241191
2
@user3241191 将元数据添加到返回体中是多余的。HTTP头部旨在为消息添加元数据。发明自己的元数据约定是一种浪费精力的行为,如果需要,这将严重限制您与其他系统集成的能力。 - Darrel Miller
它会严重限制我与其他系统集成的能力吗?它基本上只是返回一个符合所有API返回的JSON样式对象。因此,消费代码实际上只需要编写一次,并可以在整个系统中重复使用。如果一个系统可以与返回JSON样式的对象进行交互,那么就没有真正的严重限制。 - user3241191
1
@user3241191 信不信由你,在网络上并非所有系统都使用json。如果客户端发送“accept:text / plain”,您将如何向其返回响应? - Darrel Miller

4

我认为第一种选项是最好的。无论如何,如果没有错误,返回代码将为200,而不需要您做任何设置。

如果出现异常,可以抛出一个带有适当代码和消息的HttpResponseException

throw new HttpResponseException(
    Request.CreateResponse<string>(HttpStatusCode.BadRequest, 'Your message'))

不应该出现这种情况。我自己做了这个,而且结果是符合预期的。请再检查一下你的逻辑。 - Claudio Redi
啊,是的,它确实可以工作。上次我尝试时可能做错了什么。 - jcvandan
还有一件事 - 如果我这样抛出HttpResponseException:throw new HttpResponseException(Request.CreateResponse((HttpStatusCode)401, "未经授权的消息")) - 响应正文是空的。如何在正文中放置消息? - jcvandan
1
@ClaudioRedi 为什么你认为选项1比选项2“更好”? - Darrel Miller
另外,根据我的个人经验(并不是很丰富),我使用返回类型来构建自定义格式化程序以进行内容协商。如果没有使用wrap,我不知道这是否会像现在这么容易。 - Claudio Redi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接