【问题标题】:call web api by passing simple and complex parameter通过传递简单和复杂的参数调用web api
【发布时间】:2018-07-07 04:29:56
【问题描述】:

收到在控制器中找不到 http 资源或操作的错误消息。在 web api 中,我有一个 from body 和 from 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 }
);

【问题讨论】:

  • 您正在发送请求正文中的所有内容,而操作已配置为期望来自 URI 的参数。

标签: c# .net asp.net-web-api dotnet-httpclient asp.net-web-api-routing


【解决方案1】:

field1field2field4 参数应在 Url 中,而不是在请求正文中。这就是请求 URL 应如下所示的原因:http://xxx.xxx.xx.xx:1234/api/home/processfields?field1=value1&amp;field2=value2&amp;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();
}

【讨论】:

    【解决方案2】:

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

    其次,永远不要将.Result 与 HttpClient 一起使用。这是一个仅限异步的 API,您应该使用 async / await,否则只会导致死锁。

    最后,正如其他人所指出的,field1、field2 和 field4 进入查询字符串,而不是正文。如果您想要一种更有条理的方式来执行此操作,并且总体上使用较少的仪式,请考虑使用Flurl(免责声明:我是作者),它在后台使用 HttpClient:

    using Flurl.Http;
    
    var result = await BaseUrl
        .AppendPathSegment("api/home/processfields")
        .SetQueryParams(new { field1, field2, field4 })
        .PostStringAsync(field3)
        .ReceiveString();
    

    【讨论】:

      【解决方案3】:
      bodyClass obj = new bodyClass();
      obj.empName= "your param value";
      string DATA = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
      
      var client = new HttpClient();
      HttpContent content = new StringContent(DATA, UTF8Encoding.UTF8, "application/json");
      HttpResponseMessage messge = client.PostAsync("your api url", content).Result;
      
      if (messge.IsSuccessStatusCode)
      {
            string result = messge.Content.ReadAsStringAsync().Result;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多