从 ASP.NET MVC 应用程序调用 ASP.NET Web API REST 服务时出现 HTTPClient 错误
HTTPClient error when calling ASP.NET Web API REST service from ASP.NET MVC app
我有一个 ASP.NET MVC 应用程序正在调用 ASP.NET Web Api REST 服务:
public class MyClass
{
private static HttpClient client = new HttpClient();
public async Task DumpWarehouseDataIntoFile(Warehouse myData, string path, string filename) // See Warehouse class later in this post
{
try
{
//Hosted web API REST Service base url
string Baseurl = "http://XXX.XXX.XX.X:YYYY/";
//using (var client = new HttpClient()) --> I have declared client as an static variable
//{
//Passing service base url
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Serialize parameter to pass to the asp web api rest service
string jsonParam = Newtonsoft.JsonConvert.SerializeObject(myData);
//Sending request to find web api REST service resource using HttpClient
var httpContent = new StringContent(jsonParam, Encoding.UTF8, "application/json");
HttpResponseMessage Res = await client.PostAsync("api/Warehouse/DumpIntoFile", httpContent);
//Checking the response is successful or not which is sent using HttpClient
if (Res.IsSuccessStatusCode)
{
// Some other sftuff here
}
//}
}
catch (Exception ex)
{
// Do some stuff here
} // End Try
} // End DumpWarehouseDataIntoFile method
} // End class
ASP.NET Web API REST 控制器:
public class WarehouseController : ApiController
{
public bool DumpIntoFile(string data)
{
// Stuff here
}
}
我使用了 HttpClient 静态变量,我没有将它包含在 'using' 块中,因为不推荐使用 link 中的解释:YOU'RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE
执行此代码时失败并出现错误:
System.Net.Http.HttpRequestException: An error occurred while sending
the request. System.Net.WebException: The remote name could not be
resolved: 'xxx'
我想我不需要处理 HttpClient 客户端对象,对吗?
我该如何解决这个问题?
我正在使用 Visual Studio 2013 和 NET 4.5(非核心)
更新 2020/12/10:
之前的错误是由于 ASP.NET Web API REST Url 在内部 DNS 中未正确配置而发生的。
现在,在解决了之前的错误后,我得到了以下一个:
404 Not Found
下面是 client.PostAsync 返回的一些错误消息:
Ping 到 ASP.NET Web API 休息正常。
也许我的 web api 路由配置在下面的 App_Start\WebApiConfig.cs 下丢失了什么?
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Configuración y servicios de API web
// Rutas de API web
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
可能要看的点:
检查您的 WebApi 文档。 404 in web API 表示主机无法访问或您调用的端点错误。首先在浏览器中粘贴 URL 进行检查。如果它是 POST 操作并且您的机器可以访问,那么您将收到 method not supported
错误。
如果在浏览器中,如果它又是 404,但你知道它是正确的,那么你应该查看机器的 ACL(用户授权和身份验证)。该机器是否 reachable/accessible 连接到您的网络。
我在您的代码中看不到任何授权 headers。请也检查一下。
很少可能 - 如果它需要一些 pre-configured 应用程序,如 Facebook,Google 等
我假设您使用的是基于您提供的 WebApiConfig
的 Web API 2。关于您收到的 404 响应,这完全是由于在您的控制器操作中错误使用或缺少路由所致。
使用您的示例 WebApiConfig,这将启用属性路由以及使用 Web 的默认路由模板的基于约定的路由 API。默认模板不会根据action名称进行匹配,它只根据控制器名称和请求的HTTP方法(GET,POST等)进行匹配。示例 GET http://localhost:5000/api/books/2
将路由到 BooksController
并将调用与命名约定相匹配的操作方法,即 GetBookById(int id)
.
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
在您的情况下,您有一个名为 DumpIntoFile(string data)
的操作方法,它不遵循上述标准命名约定,因此路由系统不知道要调用哪个操作。您可以使用在配置中启用的属性路由来解决此问题。您需要向您的操作方法添加一个属性,该属性指定 HTTP 谓词以及应调用该方法的路由。请注意应添加到控制器的附加属性 class,它指定路由前缀。
[RoutePrefix("api/warehouse")]
public class WarehouseController : ApiController
{
// Routes POST http://localhost:5000/api/warehouse/dump
[Route("dump")]
[HttpPost]
public bool DumpIntoFile(string data)
{
//...
}
}
这会将 POST 请求路由到 http://localhost:5000/api/warehouse/dump
。显然 localhost:5000
是一个占位符,用于表示您的基本 uri 是什么。我不知道请求中的 data
有多复杂,但您可以参考有关如何处理请求正文中的数据的文档。该示例主要集中在路由部分。
这只是一个简单示例,您可以使用各种不同的属性来指定路由、接受的方法等。文档很好地概述了它并提供了大量示例。 Link 提供如下。另外,我建议返回 IHttpActionResult
或 HttpResponseMessage
类型之一,而不是简单的 bool/string/int/etc。它只是为您返回的 HTTP 响应类型提供了更多选项,这些也在文档中。
我有一个 ASP.NET MVC 应用程序正在调用 ASP.NET Web Api REST 服务:
public class MyClass
{
private static HttpClient client = new HttpClient();
public async Task DumpWarehouseDataIntoFile(Warehouse myData, string path, string filename) // See Warehouse class later in this post
{
try
{
//Hosted web API REST Service base url
string Baseurl = "http://XXX.XXX.XX.X:YYYY/";
//using (var client = new HttpClient()) --> I have declared client as an static variable
//{
//Passing service base url
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Serialize parameter to pass to the asp web api rest service
string jsonParam = Newtonsoft.JsonConvert.SerializeObject(myData);
//Sending request to find web api REST service resource using HttpClient
var httpContent = new StringContent(jsonParam, Encoding.UTF8, "application/json");
HttpResponseMessage Res = await client.PostAsync("api/Warehouse/DumpIntoFile", httpContent);
//Checking the response is successful or not which is sent using HttpClient
if (Res.IsSuccessStatusCode)
{
// Some other sftuff here
}
//}
}
catch (Exception ex)
{
// Do some stuff here
} // End Try
} // End DumpWarehouseDataIntoFile method
} // End class
ASP.NET Web API REST 控制器:
public class WarehouseController : ApiController
{
public bool DumpIntoFile(string data)
{
// Stuff here
}
}
我使用了 HttpClient 静态变量,我没有将它包含在 'using' 块中,因为不推荐使用 link 中的解释:YOU'RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE
执行此代码时失败并出现错误:
System.Net.Http.HttpRequestException: An error occurred while sending the request. System.Net.WebException: The remote name could not be resolved: 'xxx'
我想我不需要处理 HttpClient 客户端对象,对吗?
我该如何解决这个问题?
我正在使用 Visual Studio 2013 和 NET 4.5(非核心)
更新 2020/12/10: 之前的错误是由于 ASP.NET Web API REST Url 在内部 DNS 中未正确配置而发生的。
现在,在解决了之前的错误后,我得到了以下一个:
404 Not Found
下面是 client.PostAsync 返回的一些错误消息:
Ping 到 ASP.NET Web API 休息正常。
也许我的 web api 路由配置在下面的 App_Start\WebApiConfig.cs 下丢失了什么?
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Configuración y servicios de API web
// Rutas de API web
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
可能要看的点:
检查您的 WebApi 文档。 404 in web API 表示主机无法访问或您调用的端点错误。首先在浏览器中粘贴 URL 进行检查。如果它是 POST 操作并且您的机器可以访问,那么您将收到
method not supported
错误。如果在浏览器中,如果它又是 404,但你知道它是正确的,那么你应该查看机器的 ACL(用户授权和身份验证)。该机器是否 reachable/accessible 连接到您的网络。
我在您的代码中看不到任何授权 headers。请也检查一下。
很少可能 - 如果它需要一些 pre-configured 应用程序,如 Facebook,Google 等
我假设您使用的是基于您提供的 WebApiConfig
的 Web API 2。关于您收到的 404 响应,这完全是由于在您的控制器操作中错误使用或缺少路由所致。
使用您的示例 WebApiConfig,这将启用属性路由以及使用 Web 的默认路由模板的基于约定的路由 API。默认模板不会根据action名称进行匹配,它只根据控制器名称和请求的HTTP方法(GET,POST等)进行匹配。示例 GET http://localhost:5000/api/books/2
将路由到 BooksController
并将调用与命名约定相匹配的操作方法,即 GetBookById(int id)
.
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
在您的情况下,您有一个名为 DumpIntoFile(string data)
的操作方法,它不遵循上述标准命名约定,因此路由系统不知道要调用哪个操作。您可以使用在配置中启用的属性路由来解决此问题。您需要向您的操作方法添加一个属性,该属性指定 HTTP 谓词以及应调用该方法的路由。请注意应添加到控制器的附加属性 class,它指定路由前缀。
[RoutePrefix("api/warehouse")]
public class WarehouseController : ApiController
{
// Routes POST http://localhost:5000/api/warehouse/dump
[Route("dump")]
[HttpPost]
public bool DumpIntoFile(string data)
{
//...
}
}
这会将 POST 请求路由到 http://localhost:5000/api/warehouse/dump
。显然 localhost:5000
是一个占位符,用于表示您的基本 uri 是什么。我不知道请求中的 data
有多复杂,但您可以参考有关如何处理请求正文中的数据的文档。该示例主要集中在路由部分。
这只是一个简单示例,您可以使用各种不同的属性来指定路由、接受的方法等。文档很好地概述了它并提供了大量示例。 Link 提供如下。另外,我建议返回 IHttpActionResult
或 HttpResponseMessage
类型之一,而不是简单的 bool/string/int/etc。它只是为您返回的 HTTP 响应类型提供了更多选项,这些也在文档中。