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);
}
场景是:
- 如果我注释掉 POST 方法中的
[FromUri] string appCode
和测试中的 request.AddParameter("appCode", AppCode);
,则测试通过。
- 如果我在 POST 方法中包含
[FromUri] string appCode
并且我 运行 来自 POSTMAN 的方法,则测试通过。
- 如果我分别在 POST 方法中包含
[FromUri] string appCode
并在测试中包含 request.AddParameter("appCode", AppCode);
,则测试失败。错误信息:
在控制器上找不到方法
欢迎任何建议!
对您实验行为的解释
- 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() 实际执行的操作。测试通过,一切顺利!
- If I include the [FromUri] string appCode on the POST method and I run the method from POSTMAN, the test Pass.
在这里,您可能使用 POSTMAN 调用适当的 url,其中包含查询参数。测试通过,如果您正在查询的 url 具有您期望的签名,则一切正常。
- 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 测试的内容需要适合您的控制器实际实现的内容。
首先,我将解释您在场景中遇到的行为。那我给个解决办法。
- 如果我从 POST 方法中注释掉 [FromUri] 字符串 appCode
和 request.AddParameter("appCode", AppCode);从测试中,
测试通过。
在这种情况下,服务器不希望任何地方出现 appCode
并且测试也不会发送它。测试似乎通过了,但我是 误报 。服务器根本没有收到 appCode
!
- 如果我在 POST 上包含 [FromUri] 字符串 appCode
方法和我 运行 来自 POSTMAN 的方法,测试通过。
我猜你在 POSTMAN 中使用这个 URL:
http://localhost:8089/UserRoles?appCode=SomeAppCode
在这种情况下 ASP.NET Web API 从 URL 中提取 appCode
并从 body 中提取 DTO。然后服务器方法按预期执行。
- 如果我在 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);
}
在我看来,尝试使用 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);
}
场景是:
- 如果我注释掉 POST 方法中的
[FromUri] string appCode
和测试中的request.AddParameter("appCode", AppCode);
,则测试通过。 - 如果我在 POST 方法中包含
[FromUri] string appCode
并且我 运行 来自 POSTMAN 的方法,则测试通过。 - 如果我分别在 POST 方法中包含
[FromUri] string appCode
并在测试中包含request.AddParameter("appCode", AppCode);
,则测试失败。错误信息: 在控制器上找不到方法
欢迎任何建议!
对您实验行为的解释
- 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() 实际执行的操作。测试通过,一切顺利!
- If I include the [FromUri] string appCode on the POST method and I run the method from POSTMAN, the test Pass.
在这里,您可能使用 POSTMAN 调用适当的 url,其中包含查询参数。测试通过,如果您正在查询的 url 具有您期望的签名,则一切正常。
- 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 测试的内容需要适合您的控制器实际实现的内容。
首先,我将解释您在场景中遇到的行为。那我给个解决办法。
- 如果我从 POST 方法中注释掉 [FromUri] 字符串 appCode 和 request.AddParameter("appCode", AppCode);从测试中, 测试通过。
在这种情况下,服务器不希望任何地方出现 appCode
并且测试也不会发送它。测试似乎通过了,但我是 误报 。服务器根本没有收到 appCode
!
- 如果我在 POST 上包含 [FromUri] 字符串 appCode 方法和我 运行 来自 POSTMAN 的方法,测试通过。
我猜你在 POSTMAN 中使用这个 URL:
http://localhost:8089/UserRoles?appCode=SomeAppCode
在这种情况下 ASP.NET Web API 从 URL 中提取 appCode
并从 body 中提取 DTO。然后服务器方法按预期执行。
- 如果我在 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);
}