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:
- ASP.NET Exception: The remote name could not be resolved: 'apiconnector.com'
- System.Net.WebException: The remote name could not be resolved:
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?