0

I am receiving a System.Net.WebException with the message "The remote name could not be resolved" when trying to do a call to a Web Service with HttpClient in ASP.NET MVC. Bafflingly enough, I have a console application and accompanying unit test that has virtually identical code that works perfectly.

Here's the factory method that creates the HttpClient:

public HttpClient GetHttpClient(bool acceptVersion = true, string acceptType = @"application/json")
    {
        // This line was required to make this run without exception for
        // my unit test
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

        string key = "key"; // Obviously, abbreviated

        var client = new HttpClient();
        if (acceptVersion)
        {
            client.DefaultRequestHeaders.Add("Accept-version", "beta");
        }
        client.DefaultRequestHeaders.Add("AccessToken", key);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptType) { CharSet = "utf-8" });
        client.BaseAddress = new Uri("API uri"); // Obviously, edited

        return client;
    }

My factory method is literally line-for-line identical for my working unit test.

Here's the ASP.NET code:

public static async Task<double> PercentOfUsersCurrentlyActive()
    {
        string json;

        using (var client = (new ConnectionFactory()).GetHttpClient(false))
        {
            // The exception occurs on this line
            HttpResponseMessage message = await client.GetAsync("users");

            json = await message.Content.ReadAsStringAsync();
        }

        UserCollection collection = JsonConvert.DeserializeObject<UserCollection>(json);

        int numActive = collection.content.Count(usr => usr.active);

        double average = (double)((double)numActive / (double)collection.content.Count);

        return average;
    }

And my controller:

public class UserController : AsyncController
{
    // GET: User
    public async Task<ActionResult> Index()
    {
        // I get the exception on here
        double user = await Reports.General_Classes.User.GetActiveUsers();
        return View(user);
    }
}

My stack trace is:

[WebException: The remote name could not be resolved: '...']
   System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) +606
   System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) +64

[HttpRequestException: An error occurred while sending the request.]
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +28
   Reports.General_Classes.<GetActiveUsers>d__36.MoveNext() in ...\User.cs:49
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24
   Report_Retriever.Controllers.<Index>d__0.MoveNext() in ...\UserController.cs:17
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +97
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeAsynchronousActionMethod>b__36(IAsyncResult asyncResult) +17
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +48
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +48
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +48
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +48
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +22
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +48
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +29
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +48
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +129  

And here's the working code from my DLL and unit test:

[TestMethod]
public async Task GetActiveUserTests()
{
    double percent = await User.GetActiveUsers();

    Assert.IsTrue(percent >= 0 && percent <= 1);
}

And here's the GetActiveUsers method from my console application DLL (which is essentially identical to the method I'm using above):

public static async Task<double> GetActiveUsers()
{
    string json;

    using (var client = UtilityMethods.GetHttpClient(false))
    {
        HttpResponseMessage message = await client.GetAsync("users");

        json = await message.Content.ReadAsStringAsync();
    }

    UserCollection collection = JsonConvert.DeserializeObject<UserCollection>(json);

    int numActive = collection.content.Count(usr => usr.active);

    double average = (double)((double)numActive / (double)collection.content.Count);

    return average;
}

As part of my research, I read the following Stack Overflow posts:

In both of those cases, they could access the remote location from a browser but not programmatically. My case is somewhat different, though: I can perform calls against the API from a unit test, but not from an ASP.NET MVC application.

In this post, the original poster was able to access this locally but not from a server. Again, though, this doesn't exactly apply to my case because both are running locally within Visual Studio.

The result is the same no matter how many times I run them - i.e. the unit test always passes and the ASP.NET MVC call always fails.

My question, then, is why does the code work in a unit test but virtually identical code fails in ASP.NET MVC?

0 Answers0