【问题标题】:Do Get request with a complex type parameter in the request body with web api使用 web api 在请求正文中获取具有复杂类型参数的请求
【发布时间】:2014-02-03 05:13:57
【问题描述】:

我想对以下操作进行集成测试。

如何在集成测试中传递我的 requestDto 对象?

GetAsync 和 SendAsync 方法都没有用于将自定义对象传递给服务器的重载参数。

[Route("{startDate:datetime}")]
[HttpGet]
public HttpResponseMessage Get(DateTime startDate, [FromBody]LessonplannerGetRequest request)
{
    request.StartDate = startDate;
    var lessonplannerResponse = _service.GetPeriodsByWeekStartDate(request);
    return Request.CreateResponse<LessonplannerResponse>(HttpStatusCode.OK, lessonplannerResponse);
}

[Test]
public void Get_Lessons_By_Date()
{
    // Arrange
    var request = new HttpRequestMessage(HttpMethod.Get, _server.BaseAddress + "/api/lessonplanner/2014-01-14");

    var myRequestDto = new LessonplannerGetRequest();

    // Act => QUESTION: HOW do I pass the myRequestDto ???
    var response = _client.SendAsync(request, new CancellationToken()).Result;

    // Assert
    Assert.That(response.StatusCode == HttpStatusCode.OK);
}

更新

正如 Darrel Miller 所说:“从技术上讲,HTTP 说你可以发送一个正文,它只是说这个正文没有任何意义并且不能被使用。HttpClient 不会让你发送一个。”

我在这里发布了我与 HttpClient 的集成测试,该测试使用复杂类型 + FromBody 执行 Get 请求:

// Arrange
var request = new HttpRequestMessage(HttpMethod.Get, _server.BaseAddress + "/api/lessonplanner/2014-01-14");
var myRequestDto = new LessonplannerGetRequest{ FirstDayOfWeek = DayOfWeek.Sunday, SchoolyearId = 1, StartDate = DateTime.Today};
request.Content = new ObjectContent<LessonplannerGetRequest>(myRequestDto, new JsonMediaTypeFormatter());
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

// Act
var response = _client.SendAsync(request, new CancellationToken()).Result;

// Assert
Assert.That(response.StatusCode == HttpStatusCode.OK);

当然,这不是 Http 方式,有些人可能会考虑通过 FromUri/查询字符串发送复杂类型。

【问题讨论】:

  • 如果你发出一个http请求,你应该序列化你的requestDto对象并通过request.body发送。
  • HTTP 语义不允许 GET 的正文。更类似于 HTTP 的方法是在 URI 和查询字符串中传递请求数据,并使用 [FromUri] 绑定到复杂类型。只是一个想法。
  • @Badri 从技术上讲,HTTP 说您可以发送正文,它只是说正文没有任何意义并且不能使用。 HttpClient 不会让你发送一个。
  • @DarrelMiller 你说的不是真的我刚刚在我的集成测试中使用了 HttpClient 与 GET + 复杂类型 + FromBody 并且效果很好。
  • @Elisa 我收到错误消息“无法使用此动词类型发送内容主体。”

标签: asp.net-web-api integration-testing asp.net-web-api2


【解决方案1】:

HTML 规范说您不能发送带有正文的 GET。

HTTP 规范允许这样做。

WebAPI 允许它,因为它是一种服务/REST 并实现 HTTP 但不是 HTML,但许多客户端和浏览器不允许它,因为它们实现了这两个规范并试图变得严格。

至于规范(RFC1866,第 46 页;HTML 4.x 第 17.13.3 节)本身,它声明:

如果方法是“get”并且操作是 HTTP URI,用户代理会获取操作的值,附加一个 `?'到它,然后附加表单数据集,使用“application/x-www-form-urlencoded”内容类型编码。

(例如,如果您使用 GET 执行 &lt;form&gt;,它将解析所有表单参数并将它们设置在查询字符串中 ?a=b)。

就纯 HTTP 和 REST 服务的上下文而言,没有什么能阻止这种行为,但并非所有客户端都能够处理它。当涉及到 REST/WebAPI 时,最好的实践建议是不处理来自 HttpGet 的正文数据,只处理 URI 数据(相反,元数据/动作限定符通常可以容忍 POST /action?filter=all,但这是另一个讨论) .

是的,即使仅在内部使用,风险自负。由于并非所有客户端都处理它(例如 HttpRequestMessage),因此您可能会遇到麻烦。

【讨论】:

    【解决方案2】:

    您不应使用 HTTPClient 传递 GET 正文。

    【讨论】:

    • @Elisa 对不起,我误读了你的问题。您想发送带有 GET 的正文。你不能那样做。 HTTP 表示 GET 消息中的正文没有意义。
    • 我刚刚通过请求正文 + Http Get 发送了我的复杂类型,它工作正常。当 Http 规范禁止这样做时,为什么 Web API 允许它?
    • HTTP 规范并没有禁止它,但 HTML 规范可以。由于大多数客户端和浏览器都支持 HTML 和 HTTP 规范,例如 HttpClient,因此它们通常对 HTML 部分非常严格。 WebAPI 仅实现 HTTP 规范(而 MVC 实现了两者,但可能并不完全严格,不确定)。请参阅下面的答案以及指向 HTML 规范的链接。
    猜你喜欢
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2021-09-24
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多