This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I want to call an async Web Service method from inside an async method and user a WPF Window in order to ask the user for the username and Password.
The Code Looks similar to this:
private async Task GetUsers()
{
List<User> users = new List<User>();
using (var client = new HttpClient())
{
var authenticationWindow = new AuthenticateWindow();
authenticationWindow.ShowDialog();
//... Code to get the token ...
var token = "myToken";
client.BaseAddress = new Uri("http://localhost:56057/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
var response = await client.GetAsync("api/users/");
if (response.IsSuccessStatusCode)
{
users = await response.Content.ReadAsAsync<List<User>>();
}
else if (response.StatusCode == HttpStatusCode.Unauthorized)
{
throw new UnauthorizedAccessException();
}
}
foreach(var user in users)
{
}
}
If I execute this Code I get the following exception:
An unhandled exception of type 'System.NullReferenceException' occurred in PresentationFramework.dll
This happens when calling client.GetAsync("api/users/"). It has probably something to do with context switching happenening because I opened the window.
How can I solve this Problem?
The call stack just Shows "External Code".
If I remove the following two lines everything works fine:
var authenticationWindow = new AuthenticateWindow();
authenticationWindow.ShowDialog();
You have a UI element being instantiated and used within the scope of a service, try to instead separate these two from each-other. It sounds like you need to have this logic of requesting users in the AuthenticateWindow, perhaps on its Loaded event:
// Safe UI entry point for async work, i.e.; event handler.
async void OnLoaded(object sender, RoutedEventArgs e)
{
var users = await GetUsersAsync();
// Take action on the user's from the API.
}
And then have the GetUsers (renamed more appropriately to GetUsersAsync) focus only on consuming the HttpClient and corresponding API, materializing and returning the List<User> like so:
async Task<List<User>> GetUsersAsync()
{
List<User> users = new List<User>();
using (var client = new HttpClient())
{
//... Code to get the token ...
var token = "myToken";
client.BaseAddress = new Uri("http://localhost:56057/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
var response = await client.GetAsync("api/users/");
if (response.IsSuccessStatusCode)
{
users = await response.Content.ReadAsAsync<List<User>>();
}
else if (response.StatusCode == HttpStatusCode.Unauthorized)
{
throw new UnauthorizedAccessException();
}
}
return users;
}
Related
I am looking to optimize my codeā¦
I have number of API with early same structure for client and handler.
But I have some questions about disposing.
I have read the using statement automatically dispose resources (here HttpClient and HttpClientHandler).
Could I rewrite my code here:
public static async Task<IEnumerable<T>> deletePostsAsync<T>(IEnumerable<string> urls) where T : BaseReturnValues
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy, true),
UseProxy = IsProxySelected
};
using (var client = new HttpClient(httpClientHandler))
{
client.BaseAddress = new Uri(URI);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(Head.key, Head.apikey);
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
async Task<U> DeleteAsync<U>(HttpClient client, string url) where U : BaseReturnValues
{
var statusCode = -1;
var json = "_";
var isSuccess = false;
try
{
using (HttpResponseMessage response = await client.DeleteAsync(url).ConfigureAwait(false))
{
statusCode = (Int32)response.StatusCode;
json = await response.Content.ReadAsStringAsync();
isSuccess = response.IsSuccessStatusCode;
}
}
catch (Exception ex)
{
//something to catch
}
:
return record;
}
}
To this piece of code without problem? Disposing resource is always done?
public static async Task<IEnumerable<T>> deletePostsAsync<T>(IEnumerable<string> urls) where T : BaseReturnValues
{
using (var client = SetClientSettings())
{
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
async Task<U> DeleteAsync<U>(HttpClient client, string url) where U : BaseReturnValues
{
:
:
return record;
}
}
public static Httpclient SetClientSettings()
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy, true),
UseProxy = IsProxySelected
};
var client = new HttpClient(httpClientHandler);
client.BaseAddress = new Uri(URI);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(Head.key, Head.apikey);
return client;
}
So I have created a method SetClientSettings and this method create the client, the clienthandler, add some headers to client and return client.
so
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(proxy, true),
UseProxy = IsProxySelected
};
using (var client = new HttpClient(httpClientHandler))
{
client.BaseAddress = new Uri(URI);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(Head.key, Head.apikey);
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
is really equivalent to??:
using (var client = SetClientSettings())
{
var tasks = urls.Select(async url => await DeleteAsync<T>(client, url).ConfigureAwait(false));
var result = await Task.WhenAll(tasks).ConfigureAwait(false);
return result!;
}
Your two pieces of code are not equivalent. There is a small difference, that with the first snippet you will dispose the client even when the following lines (e.g. client.BaseAddress = new Uri(URI); or client.DefaultRequestHeaders.Clear();) fail. Which is better. To achieve this with SetClientSettings you would need to wrap everything into try except and .Dispose() on exception.
I have read the using statement automatically dispose resources (here HttpClient and HttpClientHandler).
The using statement turns this:
using (var instance = something)
{
// body
}
into this
var instance = something;
try
{
// body
}
finally
{
if (instance != null)
{
instance.Dispose();
}
}
That's all it does. It is a syntactic sugar.
And so in your particular case the using statement will ensure that .Dispose() is called on HttpClient, regardless of whether exception is thrown or not.
Now, do we have to dispose HttpClient? Well, they say we have to, there's no reason not to believe it. In reality the HttpClient holds sockets under the hood, which have to be closed manually when done with. And so, yes, you should always dispose HttpClient when done with.
That being said, the best thing you can do is to have a singleton HttpClient for the duration of your app, and reuse it. You can tweak it to your needs (e.g. configure it to use pooled connections) for maximal efficiency. In such scenario you don't dispose it at all.
Note: you don't have to worry about disposing HttpClientHandler. By default HttpClient will dispose it when it is disposed itself. This behaviour can be modified by using different constructor.
Yes, the code you wrote is equivalent to each other. There's an option in HttpClient contructor to not to dispose message handler - by default, it's set to true. Anyway, as already suggested, you don't have to dispose HTTP client at all. There are reasons for that.
There's alot of nice articles about best practices of using HttpClient.
Try to search for IHttpClientFactory.
I have a form that runs code and sends messages based on starting, stopping and exit or exception to a Teams WebHook.
I can get everything working except the application exit or form closed event handlers, my httpClient always wants to convert the methods to async tasks and thus they don't work if I do that. When I exit, the message is not sent on form closed or application exit.
How can I solve that? Can I use non async instead to send the message to the Teams WebHook?
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
if (finished == "finished")
{
//Teams Bot Exit
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "myURLhere"))
{
request.Content = new StringContent("{'text':'" + CusMovexNum + " Database Cleanup Tool exited.'}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await httpClient.SendAsync(request); //doesn't like this
}
}
}
if (finished == "")
{
//Teams Bot Exit
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "myURLhere"))
{
request.Content = new StringContent("{'text':'" + CusMovexNum + " Database Cleanup tool exited before finishing!'}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await httpClient.SendAsync(request); //doesn't like this
}
}
}
}
catch { }
}
If you don't need (or in this case don't want) the operations to run asynchronously, simply use the synchronous versions instead. This means that, instead of:
var response = await httpClient.SendAsync(request);
you'd use:
var response = httpClient.Send(request);
It means the form close will 'hang' for a bit (as long as the web call takes to complete), but at least it will complete, which is what you're wanting to happen.
Currently working with the outlook api, even tough I usually work with the outlook library acquired via Nuget; I have reached a limitation where I am not able to accept event invitations. So I proceeded in making a a restful call out to the the outlook api. However, when I am making the call I am getting the following message {"error":{"code":"InvalidMethod","message":"An action can only be invoked as a 'POST' request."}} when executing the call.
Bad Code
class Program
{
static void Main(string[] args)
{
var testAccept = ExecuteClientCall.AcceptEvent().Result;
}
public static async Task<bool> AcceptEvent()
{
AuthenticationContext authenticationContext = new AuthenticationContext(CrmPrototype.Helpers.AuthHelper.devTenant);
try
{
var token = await GetTokenHelperAsync(authenticationContext, CrmPrototype.Helpers.AuthHelper.OutlookAuthenticationEndpoint);
string requestUrl = "https://outlook.office.com/api/v2.0/Users/***#nowwhere.com/events('AAQkAGZiNDQxZTVkLWQzZjEtNDdjNy04OTc4LTM4NmNjM2JiOTRjNAAQAFpV0CnWR0FIpWFYRtszPHU=')/accept";
HttpClient hc = new HttpClient();
hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var method = new HttpMethod("POST");
var request = new HttpRequestMessage(method, requestUrl)
{
Content = new StringContent("{SendResponse: true}", Encoding.UTF8, "application/json")
};
HttpResponseMessage hrm = await hc.GetAsync(requestUrl);
if (hrm.IsSuccessStatusCode)
{
string jsonresult = await hrm.Content.ReadAsStringAsync();
var stophere = 0;
}
else
{
return false;
}
return true;
}
catch (Exception ex)
{
throw;
}
}
}
Maybe the reason is that you called
hc.GetAsync(requestUrl);
The doc said that this method:
Sends a GET request to the specified Uri as an asynchronous operation.
Try:
PostAsync(Uri, HttpContent)
https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx
Hope this help you.
Your variable request contains an HttpRequestMessage object that you have created, but your code presently doesn't do anything with it.
Try replacing the line
HttpResponseMessage hrm = await hc.GetAsync(requestUrl);
(which, as pointed out by the other answer, makes a GET request), with
HttpResponseMessage hrm = await hc.SendAsync(request);
I have a functioning async Task that calls a web service:
private async Task GetResult()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Username", _username);
client.DefaultRequestHeaders.Add("Action", "GET");
/* etc */
var response = await client.GetAsync(client.BaseAddress);
}
}
I would like to separate out the creation of the HttpClient object so it can be parameterized and reused:
private async Task GetResult()
{
using (var client = GetClient(_baseAddress, _username))
{
var response = await client.GetAsync(client.BaseAddress);
}
}
private static HttpClient GetClient(string Address, string Username)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Address);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Username", Username);
client.DefaultRequestHeaders.Add("Action", "GET");
/* etc */
return client;
}
}
While this appears functionally identical to me, the latter throws an AggregateException error with inner exception
Cannot Access a disposed object. Object name: 'System.Net.Http.HttpClient'.
Perhaps there is some async subtlety that I don't understand?
Get rid of the using inside of GetClient. You only use using for things that remain "in your ownership", you are "giving up ownership to the caller" when you return client;.
It is now the caller's resposability to use a using statement (which you do already correctly do in GetResult).
This has nothing to do with asnyc and is simply standard IDisposable behavior.
This is the first time i've tried making a call to an API and I'm struggling a little. I keep getting back my error message, I plan on using the json response to populate my object. The OMDB api instructions are here (not helpful though): http://www.omdbapi.com/
private static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://www.omdbapi.com/?");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("t=Captain+Phillips&r=json").Result;
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}
}
You have placed the question mark (?) on the wrong place. Try like this:
private static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://www.omdbapi.com");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("?t=Captain+Phillips&r=json");
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}
}
Notice that the question mark is here:
HttpResponseMessage response = await client.GetAsync("?t=Captain+Phillips&r=json");
and not on the base url as you placed it.
Also in order to properly write your asynchronous method you need to await on it inside and not be eagerly calling the .Result property which of course is a blocking operation.