HttpClient
:
public string BridgeSP(long SPId)
{
using (var client = new HttpClient())
{
ReadConfig();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", GenerateAuthenticationToken());
client.BaseAddress = new Uri(ApiBaseUrl);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//HTTP POST
var responseTask = client.PostAsJsonAsync(ApiActionName + "/" + SPId, SPId);
responseTask.Wait();
var result = responseTask.Result;
var readTask = result.Content.ReadAsAsync<string>();
readTask.Wait();
response = result.StatusCode + "|" + readTask.Result;
}
return response;
}
WebApi
:
[BasicAuthenticationAttribute]
[ActionName("BridgeSP")]
[System.Web.Http.HttpPost]
public HttpResponseMessage Post(long SPId)
{
try
{
Utility.QBUpdateVendor(SPId);
return Request.CreateResponse(HttpStatusCode.OK, "SP Bridged Successful ");
}
catch(Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex.Message.ToString());
}
}
WebApiConfig.cs:
config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
为什么在调用web api时会抛出此错误?
答案 0 :(得分:0)
根据MSFT documentation你应该发送没有变量SPId的uri
在这一行:
var responseTask = client.PostAsJsonAsync(ApiActionName + "/" + SPId, SPId);
您将带有SPId
的内容发送到网址&#34; ... ApiActionName / SPId&#34;但是,应该使用以下内容:
var response = httpClient.PostAsJsonAsync(String.Format("{0}/{1}", controller, action), request).Result;
最后,您应该调用response.EnsureSuccessStatusCode()以确保响应指示成功(通常为200 OK)。如果情况并非如此,则会引发异常。
最后,api发布[Route("BridgeSP/{SPId}")]
或者this post可以帮助你
答案 1 :(得分:0)
为什么在调用web api时会抛出此错误?
我打赌你的请求由于错误配置的路由而导致404 HTTP错误失败(见下文)。响应包含带有错误描述的html有效负载。但在客户端,您不检查http错误代码并尝试反序列化响应正文,因为它包含JSON字符串。这就是为什么你得到“没有MediaTypeFormatter可以从媒体类型为string
的内容中读取text/html
类型的对象”错误。
您必须在代码中进行多项修复才能避免这种情况。
首先,您尝试在URL和请求正文中传递SPId
。虽然有可能,但最好避免这种冗余。您应该选择是否要在URL或正文中传递此ID。对于标识资源的单个数字参数,首选传入URL是因为它符合REST原则。以下是对客户的适当更改:
var responseTask = client.PostAsync(ApiActionName + "/" + SPId, null);
在null
的{{1}}参数中传递content
将发送POST请求
没有身体。
您还应该调整服务器部分。您必须指定路由,以便可以从请求网址中提取PostAsync
的值:
SPId
现在可以通过[HttpPost]
[Route("BridgeSP/{SPId}")]
public HttpResponseMessage Post(long SPId)
{
// ...
网址访问您的操作了。如果要在URL中保留控制器名称,还应为控制器设置http://localhost/BridgeSP/123
属性。有关详细信息,请查看有关attribute routing的文章。
然后在客户端中,您应该在反序列化主体之前检查响应代码。这可以防止你得到你所询问的奇怪异常。最简单的方法是调用Route
方法,如果请求结束时会抛出一些HTTP错误。
以下是调整后的客户代码:
HttpResponseMessage.EnsureSuccessStatusCode()
确保在客户端(public string BridgeSP(long SPId)
{
using (var client = new HttpClient())
{
ReadConfig();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", GenerateAuthenticationToken());
client.BaseAddress = new Uri(ApiBaseUrl);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//HTTP POST
var responseTask = client.PostAsync(ApiActionName + "/" + SPId, null);
var result = responseTask.Result;
// This will throw if request finished with some HTTP error
result.EnsureSuccessStatusCode();
var readTask = result.Content.ReadAsAsync<string>();
readTask.Wait();
response = result.StatusCode + "|" + readTask.Result;
}
return response;
}
)配置了正确的API URL。