Willy
Willy

Reputation: 10648

HTTPClient error when calling ASP.NET Web API REST service from ASP.NET MVC app

I have an ASP.NET MVC application which is invoking a ASP.NET Web Api REST service:

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

The ASP.NET Web API REST Controller:

public class WarehouseController : ApiController
{ 
    public bool DumpIntoFile(string data)
    {
           // Stuff here
    }
}

I have used an HttpClient static variable, I am not enclosing it within a 'using' block because of it is not recommended as explained in this link: YOU'RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE

When this code is executed it fails with the error:

System.Net.Http.HttpRequestException: An error occurred while sending the request. System.Net.WebException: The remote name could not be resolved: 'xxx'

I think I do not need to dispose HttpClient client object, right?

How can I solve this?

I am using Visual Studio 2013 and NET 4.5 (Not Core)

UPDATE 2020/12/10: Previous error was occurring because of ASP.NET Web API REST Url was not configured correctly in the internal DNS.

Now after solving previous error I get below one:

404 Not Found

Below some messages of the error returned by client.PostAsync:

enter image description here

Ping to ASP.NET Web API Rest is working.

Maybe it is something missing in my web api routes configuration under App_Start\WebApiConfig.cs below?

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 }
        );
    }
}

Upvotes: 0

Views: 2564

Answers (2)

jdewerth
jdewerth

Reputation: 564

I will assume you're using Web API 2 based on the WebApiConfig that you provided. In regards to the 404 response you're receiving, this stems entirely from the incorrect use of, or lack thereof, routing in your controller actions.

Using your example WebApiConfig, this would enable attribute routing as well as convention-based routing using the default route template for a Web API. The default template will not match according to action name, it only matches according to the controller name and the HTTP method of the request (GET, POST, etc.). Example GET http://localhost:5000/api/books/2 will route to the BooksController and will invoke the action method that matches the naming convention i.e. GetBookById(int id).

config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

In your case, you have an action method called DumpIntoFile(string data) which doesn't follow the standard naming convention above, therefore the routing system does not know which action to invoke. You can fix this by using the attribute routing that you enabled in the config. You need to add an attribute to your action method that specifies the HTTP verb as well as the route which should invoke the method. Note the additional attribute that should be added to the controller class, which specifies a route prefix.

[RoutePrefix("api/warehouse")]
public class WarehouseController : ApiController
{
    // Routes POST http://localhost:5000/api/warehouse/dump
    [Route("dump")]
    [HttpPost]
    public bool DumpIntoFile(string data)
    {
        //...
    }
}

This will route a POST request to http://localhost:5000/api/warehouse/dump. Obviously the localhost:5000 is a placeholder for whatever your base uri would be. I don't know how complex your data in the request is but you can reference the docs regarding how to deal with the data in your request body. The example is primarily focused on the routing portion.

This is just a quick example, there are various different attributes that you could use to specify the routes, accepted methods and so on. The docs outline it pretty well and provide plenty of examples. Link is provided below. On an additional note, I'd suggest returning one of the IHttpActionResult or HttpResponseMessage types instead of a simple bool/string/int/etc. It just gives you more options for the type of HTTP response that you're returning, these are also in the docs.

Docs: https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

Upvotes: 1

Amit Ranjan
Amit Ranjan

Reputation: 214

Possible points to look:

  1. Check your WebApi documents. 404 in web API means, either host is not reachable or the endpoint your are calling is wrong. Check that first by pasting the URL in your browser. If its a POST operation and accessible by your machine, then you will get a method not supported error.

  2. If in the browser, if its 404 again but you know its correct then you should look into the ACL (User Authorization and Authentication) of the machine. Whether that machine is reachable/accessible to your network or not.

  3. I can't see any authorization headers in your code. Please check for that as well.

  4. Rarely possible - If it requires some pre-configured app like Facebook, Google etc.

Upvotes: 1

Related Questions