通过传递简单和复杂的参数来调用web api

问题描述 投票:2回答:3

获取控制器中找不到http资源或操作的错误消息。在web api中,我有一个来自body和uri参数。

[HttpPost]        
public IHttpActionResult processfields(
    [FromUri]string field1,
    [FromUri]string field2, 
    [FromBody] string field3, 
    [FromUri]string field4
){...}

在客户端我想通过做 - 来调用web api

using (var client = new HttpClient())
{
    //set up client
    client.BaseAddress = new Uri(Baseurl);
    client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


     var values = new Dictionary<string, string>();
     values.Add("field1", field1);
     values.Add("field2", field2);
     values.Add("field3", field3);
     values.Add("field4", filed4);


     var jsonString = JsonConvert.SerializeObject(values);
     try
     {

         HttpResponseMessage Res = client.PostAsync("api/home/processfields", new StringContent(jsonString, Encoding.UTF8, "application/json")).Result;
         var result = Res.Content.ReadAsStringAsync();
     }
}

在调试时,它执行上面的最后一行,但没有任何反应,错误信息说 -

{“Message”:“找不到与请求URI'http://xxx.xxx.xx.xx:1234/api/home/processfields'匹配的HTTP资源。”,“MessageDetail”:“在控制器'home'上找不到与请求匹配的操作。”}

我的webapi.config有

// Web API routes
config.MapHttpAttributeRoutes();


config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
c# .net asp.net-web-api dotnet-httpclient asp.net-web-api-routing
3个回答
3
投票

field1field2field4参数预计在Url中,而不是在请求正文中。这就是为什么请求Url应该是这样的:http://xxx.xxx.xx.xx:1234/api/home/processfields?field1=value1&field2=value2&field4=value4

field3从身体反序列化。但是因为它是字符串参数,所以请求体不应该构建为JSON对象:

{
  "field3": "value3"
}

但作为JSON字符串:

"value3"

以下是调整后的客户端代码:

using (var client = new HttpClient())
{
    //set up client
    client.BaseAddress = new Uri(Baseurl);
    client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var requestUri = new Uri($"api/home/processfields?field1={HttpUtility.UrlEncode(field1)}&field2={HttpUtility.UrlEncode(field2)}&field4={HttpUtility.UrlEncode(field4)}", UriKind.Relative);
    var content = new StringContent($"\"{field3}\"", Encoding.UTF8, "application/json");
    var response = await client.PostAsync(requestUri, content);
    var result = await response.Content.ReadAsStringAsync();
}

3
投票

首先,看一下Web API方法签名,我认为这里根本不涉及任何JSON。所以我认为你可以跳过设置Accept标题。 (如果[FromBody]参数是一个复杂的对象而不是一个字符串,那么JSON序列化很可能会发挥作用。)

其次,永远不要使用qttxswpoi和HttpClient。它是一个仅支持异步的API,您应该使用.Result / async,否则您只是在邀请死锁。

最后,正如其他人所指出的那样,field1,field2和field4进入查询字符串,而不是正文。如果你想要一种更有条理的方式来做到这一点,并且整体仪式较少,可以考虑使用await(免责声明:我是作者),它使用了HttpClient:

Flurl

0
投票
using Flurl.Http;

var result = await BaseUrl
    .AppendPathSegment("api/home/processfields")
    .SetQueryParams(new { field1, field2, field4 })
    .PostStringAsync(field3)
    .ReceiveString();
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.