HttpRequestException when using HttpClient? - c#

I was having a WebClient that was requesting an URL. I wanted to do the same thing within a UWP application, and I saw that I had to import Microsoft.Net.Http and use HttpClient.
So I replaced this(that was in a Class library):
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
string content = client.DownloadString(url);
By this in a PCL library:
HttpClient client = new HttpClient();
string content = await client.GetStringAsync(url);
And now I got this exception:
System.Net.Http.HttpRequestException occurred
HResult=-2147012867
Message=An error occurred while sending the request.
Source=System.Net.Http
StackTrace:
at System.Net.Http.HttpClientHandler.<SendAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at XXXX.YYYY.MHDJ.ZZZZ.<ParsePage>d__4.MoveNext()
InnerException:
ErrorCode=-2147012867
HResult=-2147012867
Message=Le texte associé à ce code d’erreur est introuvable.
Impossible d'établir une connexion avec le serveur
Source=""
StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpHandlerToFilter.<SendAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClientHandler.<SendAsync>d__1.MoveNext()
InnerException:
I don't think the issue is the Headers, so what is?

The HRESULT code -2147012867 in hex is 0x80072EFD. The 0x8007 prefix means it's actually an HRESULT wrapper around a Win32 error code. The original Win32 error code is 0x2EFD.
The Win32 error code list tells us that values 0x2EE0 through 0x2F8F are ERROR_INTERNET_* error codes, which sounds like the right kind of error. After following the link to the Win32 ERROR_INTERNET_* error code listing, we can convert our error code 0x2EFD back to decimal (12029) and discover it is error ERROR_INTERNET_CANNOT_CONNECT:
The attempt to connect to the server failed.
Rather generic, and not much help.
I'd recommend trying the connection again, ensuring that your application has appropriate permissions and the device actually has a working Internet connection. If that doesn't work, try adding the UserAgent header back in; it's possible that the networking stack on your device insists on it.
Update: Tracking down the error code meaning was rather tedious, so I wrote an app to do it.

Experienced the 0x80072efd problem. Has cost me hours if not days to solve. The solution that worked for me was the following command from an admin command prompt:
netsh winhttp reset proxy

There are so many ways to do things, and I'm not suggesting that this is the best way, but this is how I construct my methods. This example is what I use to return a list of U.S. State objects that are provided in JSON format. One important note... this is in a Universal Windows class library, not a PCL... but I do not believe it uses anything that a PCL does not have access to.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using System.Threading.Tasks;
//IStateInfo is my model class interface
public async Task<IList<IStateInfo>> GetAllStatesAsync()
{
List<IStateInfo> states = new List<IStateInfo>();
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://YourBaseApiHere");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string url = "lookup/usstates";
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
//deserialize into client class Newtonsoft JSON used here
var lst = JsonConvert.DeserializeObject<List<StateInfo>>(json);
states.AddRange(lst);
}
else
{
//notify of failed web call here
}
}
}
catch (Exception e)
{
//notify of error
}
return states;
}

Related

GetConversationMembersAsync returning 403 (Forbidden)

I'm working on a messaging extension and am trying to get the email address of the user who is using the app.
This app is being used internally and I'm using the email address to query Active Directory for the user's username.
When attempting to use the GetConversationMembersAsync method I receive a 403 (Forbidden) exception.
I am running this through IIS Express in Visual Studio 2017.
[BotAuthentication, TenantFilter]
public class MessagesController : ApiController
{
static string AppID = ConfigurationManager.AppSettings["MicrosoftAppId"];
static string AppPassword = ConfigurationManager.AppSettings["MicrosoftAppPassword"];
[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{
using (var connector = new ConnectorClient(new Uri(activity.ServiceUrl)))
{
var members = await connector.Conversations.GetConversationMembersAsync(activity.Conversation.Id);
System.UnauthorizedAccessException
HResult=0x80070005
Message=Authorization for Microsoft App ID XXX failed with status code Forbidden and reason phrase 'Forbidden'
Source=Microsoft.Bot.Connector
StackTrace:
at Microsoft.Bot.Connector.JwtTokenRefresher.d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClient.d__58.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Bot.Connector.Conversations.d__10.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Connector.ConversationsExtensions.d__11.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at NewApp.Controllers.MessagesController.d__2.MoveNext() in C:\Users\xxxx\source\repos\NewApp\NewApp\Controllers\MessagesController.cs:line 25
Inner Exception 1:
HttpRequestException: Response status code does not indicate success: 403 (Forbidden).
I found a similar issue here: Authorization for Microsoft App ID xxx failed with status code Forbidden and reason phrase 'Forbidden'. But that is not specifically for Microsoft Teams. connector-> Credentials->OAuthScope is showing "api.botframework.com/.default" but I believe that is correct for Teams.
My MicrosoftAppId and MicrosoftAppPassword are correct. If I comment out [BotAuthentication, TenantFilter] I get a 401 Unauthorized exception. If I comment out the line with GetConversationMembersAsync the app works.
I'm following the instructions here to attempt to get this context info: https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/bots/bots-context.
I know this is an old question, but I had the same issue and found the solution, in case it helps someone. You need to be sure and add MicrosoftAppCredentials.TrustServiceUrl(serviceURL);, as follows:
using (var connector = new ConnectorClient(new Uri(activity.ServiceUrl)))
{
// the line below is the new required item
MicrosoftAppCredentials.TrustServiceUrl(serviceURL);
var members = await connector.Conversations.GetConversationMembersAsync(activity.Conversation.Id);
...

Generate Embed Token For Create Issue

I have an issue with getting embed token. I've done all 5 steps which is described in this link (5 steps to push data into a dataset) and everything works perfectly: datasets are created, tables are created and filled in with data without any problems.
I have a task to embed a datasets (not reports) to web page.
I found this page (Power BI Embeded Sample) which shows how embed report/dataset/dashboard/tile will look like. And on this page there is an embed token.
I googled a little and found this page (Generate Embed Token Example) which describes the looks oh HTTP POST requests. I did the part for datasets. Here is my code example:
private static void generateEmbedToken()
{
// TokenCredentials Initializes a new instance of the
// Microsoft.Rest.TokenCredentials class with
// the given 'Bearer' token.
var credentials = new TokenCredentials(token);
// Initialize PowerBIClient with credentials
var powerBIclient = new Microsoft.PowerBI.Api.V2.PowerBIClient(credentials)
{
// BaseUri is the api endpoint, default is https://api.powerbi.com
BaseUri = new Uri("https://api.powerbi.com")
};
try
{
// Create body where accessLevel = View, datasetId = "" by default
var requestParameters = new GenerateTokenRequest(TokenAccessLevel.Create, datasetId, true);
// Generate EmbedToken This function sends the POST message
//with all parameters and returns the token
EmbedToken token = powerBIclient.Reports.GenerateTokenForCreate(requestParameters);
embedToken = token.Token;
}
catch (Exception exc)
{
Console.WriteLine(exc.ToString());
}
}
and I got next error:
Microsoft.Rest.HttpOperationException: Operation returned an invalid status code 'NotFound'
at Microsoft.PowerBI.Api.V2.Reports.<GenerateTokenForCreateWithHttpMessagesAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.PowerBI.Api.V2.ReportsExtensions.<GenerateTokenForCreateAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.PowerBI.Api.V2.ReportsExtensions.GenerateTokenForCreate(IReports operations, GenerateTokenRequest requestParameters)
at PushDataApp.Program.generateEmbedToken() in C:\Users\PC\Documents\Visual Studio 2017\Projects\PushDataApp\PushDataApp\Program.cs:line 388
here is line 388:
EmbedToken token = powerBIclient.Reports.GenerateTokenForCreate(requestParameters);
I don't know why it's happening.
I took this code from here (Generate Embed Token Example), but I did some changes for my purposes (because I need dataset and not report).
I'll appreciate any help.
I have come across a similar error when attempting to embed using Power BI. I recommend using a tool like Fiddler to intercept the communication between your application and Power BI and finding out the error code that is actually being returned.
The following article from Telerik shows how to intercept traffic using Fiddler: Capturing Traffic from .NET Services with Fiddler

.Net Core ClientWebSocket: Unable to connect to server

I'm building a web application that connects to a Predix Timeseries instance to ingest data through a websocket. When I attempt to create the socket, I get this exception:
System.Net.WebSockets.WebSocketException: 'Unable to connect to the
remote server'
I'm using this code to create my websocket, with my error being thrown on the ConnectAsync call:
public async Task openWebSocket()
{
_socket = new ClientWebSocket();
_socket.Options.SetRequestHeader(headerName: "predix-zone-id", headerValue: PREDIX_ZONE_ID_HERE);
_socket.Options.SetRequestHeader(headerName: "authorization", headerValue: "Bearer " + AUTH_TOKEN_HERE);
_socket.Options.SetRequestHeader(headerName: "content-type", headerValue: "application/json");
CancellationToken token = new CancellationToken();
var uri = new Uri(uriString: "wss://gateway-predix-data-services.run.aws-usw02-pr.ice.predix.io/v1/stream/messages");
await _socket.ConnectAsync(uri: uri, cancellationToken: token);
}
and here is my exception's stack trace:
System.Net.WebSockets.WebSocketException occurred
HResult=0x80004005
Message=Unable to connect to the remote server
Source=<Cannot evaluate the exception source>
StackTrace:
at System.Net.WebSockets.WebSocketHandle.<ConnectAsyncCore>d__20.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__16.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at PROJECTNAME.Services.TimeseriesService.<openWebSocket>d__6.MoveNext() in %PROJECTLOCATION%\Services\%SERVICENAME%.cs:line 34
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at PROJECTNAME.Services.TimeseriesService.<Initialize>d__5.MoveNext() in %PROJECTLOCATION%\Services\%SERVICENAME%.cs:line 21
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at PROJECTNAME.Program.<Initialize>d__1.MoveNext() in %PROJECTLOCATION%\Program.cs:line 52
Inner Exception 1:
WebSocketException: Unable to connect to the remote server
The inner exception stack track has little more information, but noting the ThrowOnInvalidConnectState() that might be useful:
at System.Net.WebSockets.WinHttpWebSocket.ThrowOnInvalidConnectState()
at System.Net.WebSockets.WinHttpWebSocket.<ConnectAsync>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketHandle.<ConnectAsyncCore>d__20.MoveNext()
I'm not sure what else to try - lots of other posts on SO at least have some useful information in the inner exception.
I've also attempted to use Fiddler. I can see message for other services, including my auth token retrieval from UAA, but nothing from this service.
Am I missing some configuration steps somewhere? Any help or guidance would be appreciated.
I figured out the issue. The three required headers for the Predix Timeseries are:
Predix-Zone-Id: zone_id_here
Authorization: Bearer auth_token_here
Origin: "https:// hostname_here
My problem is that I tried the Origin header, but the Predix VCAP_APPLCIATION environmental variable for the application_uris doesn't include the "https://". Once I added it manually ("https://" + uri) it worked fine.
I haven't done this in C#, but "Unable to connect" sounds like it could be a network issue. Can you open a websocket to another server? Maybe this one?
https://www.websocket.org/echo.html
Could be a proxy server issue? Can you try from a different network?

C# REST - Send Request Body, Receive Response Body

I'm using the WebClient class. I've had some luck with the OpenReadTaskAsync method with a GET, but right now, I want to call a POST, or PUT REST method. I figured that I should use UploadStringTaskAsync. But, when I call this method on a working REST service, I get this error:
System.Net.WebException: An exception occurred during a WebClient request. ---> System.NotSupportedException: Specified method is not supported on this request.
at System.Net.Browser.BrowserHttpWebRequest.set_Method(String value)
at System.Net.WebClient.GetWebRequest(Uri address)
at System.Net.WebClient.UploadStringAsync(Uri address, String method, String data, Object userToken)
--- End of inner exception stack trace ---
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at CF.RESTClientDotNet.Silverlight.Sample.MainPage.d__3.MoveNext()
This is the code
var webClient = new WebClient();
var returnValue = await webClient.UploadStringTaskAsync(uri.AbsoluteUri, "POST", bodyString);
I ended up completely redesigning my library. There are samples here:
https://bitbucket.org/MelbourneDeveloper/restclient-.net/src/master/
NuGet: Install-Package RESTClient.NET

Windows.Web.Http.HttpClient#GetAsync throws an incomplete exception when invalid credentials are used with basic authentication

I am working on a Windows Runtime Component which makes API calls. Until earlier today I used the HttpClient and related models from System.Net but switched over to Windows.Web instead to leverage the WinRT streams.
Aside from changing the using statements, swapping HttpContent to IHttpContent and using the WindowsRuntimeExtensions to change my IInputStream to Stream for JSON.NET, I didn't have to do anything special. However suddenly 3 out of my 16 tests fail whereas previously everything worked.
All 3 (integration) tests validate that I receive an error response when logging in with invalid credentials. There are other tests that include logging in as well (but with valid credentials) and they work just fine. The given error message is of type AggregateException and has as message
System.AggregateException: One or more errors occurred. ---> System.Exception: Element not found.
A dialog cannot be displayed because the parent window handle has not been set.
The exception contains HRESULT values. The outerexception has value -2146233088 which corresponds to 0x80131500 while the innerexception has -2147023728 which corresponds to 0x80070490. Neither of those are a known error code on the MSDN page.
Following investigation:
0x80131500 corresponds to COR_E_EXCEPTION
0x80070490 corresponds to ERROR_NOT_FOUND
Stacktrace:
Result StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at xx.Models.Requests.GetRequest.<ExecuteRequestAsync>d__0.MoveNext() in c:\Users\jeroen\Github\Windows-app\xx\xx\Models\Requests\Request.cs:line 17
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at xx.ApiDispatcher.<ExecuteAsync>d__0`2.MoveNext() in c:\Users\jeroen\Github\Windows-app\xx\xx\ApiDispatcher.cs:line 40
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at xx.ApiDispatcher.Execute[TCallResult,TResponseObject](ApiCall`2 call) in c:\Users\jeroen\Github\Windows-app\xx\xx\ApiDispatcher.cs:line 22
Originally my question was worded somewhat differently because the actual problem seemed to be hidden. I have found out that the GET request by the HttpClient returns back to the caller instead of awaiting the result of the call (and executing the rest of the method).
In my project, executing the line var data = await myHttpClient.GetAsync(url); will return to the calling method with a non-constructed object and subsequent lines that come after the GetAsync() call are simply not executed.
Adding .ConfigureAwait(false) to stop it from going back did not make a difference.
The AggregateException is thrown when a user tries to login with invalid credentials. For some reason the HttpClient decides to throw an exception then without giving me a return value I could use. The problem here is that it does not tell me what kind of exception: catching COMException, TaskCanceledException, AggregateException and Exception only trigger the latter.
I have also found out that asynchronous integration tests do not work well with the multithreaded MSTest environment, so that explains several other failed tests that I had (but worked just fine individually)
I also, finally, have an example that demonstrates the problem (but I can't provide a webservice that takes basic auth)!
[TestMethod]
public void TestMethod3()
{
Assert.IsTrue(new Test().Do().AsTask().Result);
}
public sealed class Test
{
public IAsyncOperation<bool> Do()
{
return DoSomething().AsAsyncOperation();
}
private async Task<bool> DoSomething()
{
var client = new HttpClient();
var info = "jeroen.vannevel#something.com:nopass";
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(info));
client.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Basic", token);
var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));
return true;
}
}
Executing this code with a valid password will return true while an invalid password will throw an AggregateException.
Right now I am working around the problem by catching a general Exception around the call to GetAsync() but this is very rudimentary and I'd like to know why this incomplete exception is thrown in the first place.
After reconstructing your example and playing around, I figured out what happens.
var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));
The GetAsync method invokes the HTTP request with invalid credentials. What happens is that the returned request tries to look for a window where you can enter the correct credentials, but doesn't find one. Hence it throws an Element Not Found while searching for that window.
This can be fixed by creating a HttpBaseProtocolFilter and setting the AllowUI property to false and then passing it to the HttpClient:
private async Task<bool> DoSomething()
{
var httpBaseFilter = new HttpBaseProtocolFilter
{
AllowUI = false
};
var client = new HttpClient(httpBaseFilter);
var info = "jeroen.vannevel#something.com:nopass";
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(info));
client.DefaultRequestHeaders.Authorization = new HttpCredentialsHeaderValue("Basic", token);
var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));
return true;
}
Setting AllowUI on HttpBaseProtocolFilter to false will stop this error.
If however you do want a dialog box to display, allowing the user to enter credentials, then the web request needs to be started on the UI thread.
I think the problem is that the exception is actually thrown by your call to EnsureSuccessStatusCode.
Did you try adding HttpResponseMessage class EnsureSuccessStatusCode() method and check.
http://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage.ensuresuccessstatuscode.aspx
After this line:
var data = await client.GetAsync(new Uri("https://mytestdomain/v2/apikey?format=Json"));
date.EnsureSuccessStatusCode();

Categories