Web API POST 使用 RestSharp 添加 FromUri 参数失败

Web API POST failed added the FromUri Parameter with RestSharp

在我看来,尝试使用 RestSharp 客户端使用 WebApi POST 方法时发生了一些奇怪的事情。以下代码分别适用于服务器(WebApi)和客户端。

服务器 WebApi

[Route("UserRoles")]
[AllowAnonymous]
public IHttpActionResult Post(
    [FromBody] UserroleDto userroleDto,
    [FromUri] string appCode)
{
  return OK();
}

测试客户端

[TestInitialize()]
public void Initialize()
{
    _restClient = new RestClient("http://localhost:8089");
}

[TestMethod]
public void Can_Store_A_Userrole_Via_REST_WebAPI()
{
    var request = new RestRequest(ApiBasePath, Method.POST);

    request.AddUrlSegment("segment", "UserRoles");
    request.RequestFormat = DataFormat.Json;
    request.AddBody(
        new UserroleDto()
        {
            UserRoleId = -1,
            Role = "Developer"
        });

    request.AddHeader("appCode", AppCode);
    //request.AddParameter("appCode", AppCode);

    _restClient.Execute(request);
}

场景是:

  1. 如果我注释掉 POST 方法中的 [FromUri] string appCode 和测试中的 request.AddParameter("appCode", AppCode);,则测试通过。
  2. 如果我在 POST 方法中包含 [FromUri] string appCode 并且我 运行 来自 POSTMAN 的方法,则测试通过。
  3. 如果我分别在 POST 方法中包含 [FromUri] string appCode 并在测试中包含 request.AddParameter("appCode", AppCode);,则测试失败。错误信息: 在控制器上找不到方法

欢迎任何建议!

对您实验行为的解释

  1. If I commend it out the [FromUri] string appCode from the POST method and the request.AddParameter("appCode", AppCode); from the Test, the test Pass.

如果没有 [FromUri],您的控制器希望通过请求 body 接收 AppCode,这正是 RestSharp.AddParameter() 实际执行的操作。测试通过,一切顺利!

  1. If I include the [FromUri] string appCode on the POST method and I run the method from POSTMAN, the test Pass.

在这里,您可能使用 POSTMAN 调用适当的 url,其中包含查询参数。测试通过,如果您正在查询的 url 具有您期望的签名,则一切正常。

  1. If I include the [FromUri] string appCode on the POST method and the request.AddParameter("appCode", AppCode); on the Test respectively, the test fail. Error message: Method Not Found on the Controller

在这里,它失败了,因为控制器希望接收 AppCode 作为查询参数。 (就像你可能用 POSTMAN 做的那样)。但是通过使用 RestSharp.AddParameter(),您可能没有在右侧 url 发送查询,因此出现错误。

如何解决问题:定义你的api路线

你必须定义的是我的路线应该是什么样子

换个方式问,有人会说 我想如何查询我的 api?

选项 1:使用查询参数

[FromUri] 将定义您的控制器,因此它将响应如下请求:

localhost:8099/UserRoles?appcode=一些东西

如果这是您希望 api 拥有的 url,则可能会相应地使用 RestSharp:

var myAppCode="FOO"; var url = "localhost:8099/UserRoles?appCode={appCodeToQuery}"; request.addUrlSegment("appCodeToQuery",myAppCode);

选项 2:使用 POST body

您可以选择另一种风格 api 路线,例如:

localhost:8099/UserRoles.

因此,您可以使用 POST 的请求 body 传递一些数据,例如:

var myAppCode="FOO"; request.addParameter("appCode",myAppCode);

应该POST数据通过请求BODY。

选项 3:使用请求 header

此外,我怀疑您是否想在 Header 中传递 appCode。 这是 RestSharp 将执行的操作,如果您调用:

request.AddHeader("appCode", AppCode);

其他选项?

是的,还有其他选项可用于将数据发送到您的 API。您将使用 RestSharp 测试的内容需要适合您的控制器实际实现的内容。

首先,我将解释您在场景中遇到的行为。那我给个解决办法。

  1. 如果我从 POST 方法中注释掉 [FromUri] 字符串 appCode 和 request.AddParameter("appCode", AppCode);从测试中, 测试通过。

在这种情况下,服务器不希望任何地方出现 appCode 并且测试也不会发送它。测试似乎通过了,但我是 误报 。服务器根本没有收到 appCode

  1. 如果我在 POST 上包含 [FromUri] 字符串 appCode 方法和我 运行 来自 POSTMAN 的方法,测试通过。

我猜你在 POSTMAN 中使用这个 URL:

http://localhost:8089/UserRoles?appCode=SomeAppCode

在这种情况下 ASP.NET Web API 从 URL 中提取 appCode 并从 body 中提取 DTO。然后服务器方法按预期执行。

  1. 如果我在 POST 方法中包含 [FromUri] 字符串 appCode 并且 request.AddParameter("appCode", AppCode);分别在测试中, 测试失败。错误消息:在控制器上找不到方法

失败的原因是 appCode 被添加到 body。但是,服务器希望它在 uri 中。因此,框架无法找到与 uri 匹配的方法并抛出上述错误。

解决方案

如果可以,我会更改路线和您的操作:

[Route("UserRoles/{appCode}"]
[AllowAnonymous]
public IHttpActionResult Post(string appCode, UserroleDto userroleDto)
{
    return OK();
}

通过此更改,url 变为:

http://localhost:8089/UserRoles/SomeAppCode

和 body 可以放在 body.

您的测试代码将是:

[TestMethod]
public void Can_Store_A_Userrole_Via_REST_WebAPI()
{
    var request = new RestRequest(ApiBasePath, Method.POST);

    request.AddUrlSegment("segment", "UserRoles");
    request.AddUrlSegment("segment", AppCode);
    request.RequestFormat = DataFormat.Json;
    request.AddBody(
        new UserroleDto()
        {
            UserRoleId = -1,
            Role = "Developer"
        });

    _restClient.Execute(request);
}