Visual Studio breakpoint inside HttpClient.GetAsync call not getting hit - c#

I'm trying to debug an asynchronous call from a test script inside my .NET webservice, but the breakpoints inside my async call are never getting hit. I even tried putting a Debugger.Break() inside of it. Below is the calling code...
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(ConfigurationManager.AppSettings["BaseAddress"]);
string uri = "/api/Rd_Regions";
// Below is the line of code I want to step into, but it won't step into the 'client.GetAsync(uri)'...
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
// Convert the result into business object
// Do stuff...
}
else do other stuff...
and the part of the webservice that should be getting called where the breakpoints are is here, the first is the context of the web api, followed by the method being called. I'd be happy if it stopped in either...
public partial class PIMSContext : DbContext
{
public PIMSContext()
: base(new OracleConnection(Security.ConfigurationReader.GetAppSetting("PIMS")), true)
//: base(new OracleConnection(ConfigurationManager.ConnectionStrings["PIMS"].ConnectionString), true)
etc....
And here is the method that is ultimately called:
// GET: api/RD_REGIONS
public IQueryable<RD_REGIONS> GetRD_REGIONS()
{
// I want the debugger to stop here!
Debugger.Break();
return db.RD_REGIONS;
}
Am I missing something? Is it not possible to step into this asynchronous call?
Any insight is appreciated.

Forgot to update with the answer earlier - it turns out I was accidentally debugging in Release mode (VS2015). Switching to Debug mode fixed it - all breakpoints started behaving as expected.

If i have understood you correctly - all breakpoints listed above are not getting hit? Not in await client.GetAsync(uri); neither in web-service GetRD_REGIONS() ? Is the code following after client.GetAsync not reached?
If it's true - maybe this method is never completed?
await client.GetAsync(uri);
Than it's possible that you are getting an exception in this place. Try to surround your GetAsync method with try/catch and place the breakpoint inside the catch block. Something like this:
...
HttpResponseMessage response = null;
try {
response = await client.GetAsync(uri);
}
catch (Exception e) {
throw e; //breakpoint goes here
}
...
Sometimes, because of your method is asynchronous, unhandled exceptions can't be registered globally by debugger or event-log. You can get this exception only with try/catch.

Related

I am not getting any output and i don't know why

using System;
using System.Text;
namespace ConsoleApp7
{
class Program
{
static void Main(string[] args)
{
YourClient client = new YourClient();
client.Put();
}
public class YourClient
{
private readonly HttpClient _client;
public YourClient()
{
_client = new HttpClient();
}
public async Task Put() // must be async
{
using (var request = new HttpRequestMessage(HttpMethod.Put, "https://api.minecraftservices.com/minecraft/profile/name/egg"))
{
request.Headers.Add("Authorization", "Bearer token");
request.Content = new StringContent("body", Encoding.UTF8, "content-type");
using (var response = await _client.SendAsync(request))
{
var data = await response.Content.ReadAsStringAsync();
var code = response.StatusCode;
Console.WriteLine(Convert.ToString(code));
// do something with data
}
}
}
}
}
}
I'm not getting any output and I don't know why. I'm trying to print the response code of the request but nothing is output, is it to do with my method?
I have tried printing hi after Client.Put() and it was printed, so I know that my code is actually running, I just don't know why it isn't printing the status code ...
The excellent comment by Prolog points out one of two issues. If your Console app is built on < C# 7.1 you will need a workaround to prevent the app from exiting (before the request has time to process) so in this case add Console.ReadKey() as the very last line. This will spin the message loop until you hit a key. But this is not the main issue and I would like to offer a couple of debugging tips.
The big issue is this:
If I run your code, your http request is failing and is throwing a System.FormatException
Usually this type of exception is not set to Break when Thrown. (You can verify this by looking in the Exception Settings window.) Unfortunately, this is giving you a silent failure in this case, so you must take matters into your own hands to observe it.
Suggestions for debugging your code
Use a try-catch block around any code that has any likelihood of failing.
Use System.Diagnostics.Debug.Assert which will cause your program to break on a line if any condition expression evaluates to false (but only when you're running in Debug mode not Release mode).
Add output statements to trace execution. Using Debug.WriteLine will send messages to the Output window (but again, only in Debug mode). Alternatively, since we have a Console app here, I'm using the main app window to output trace statements.
Example using 1-3:
public async Task Put() // must be async
{
Console.WriteLine("Begin Put()");
try
{
using (var request = new HttpRequestMessage(HttpMethod.Put, "https://api.minecraftservices.com/minecraft/profile/name/egg"))
{
request.Headers.Add("Authorization", "Bearer token");
request.Content = new StringContent("body", Encoding.UTF8, "content-type");
using (var response = await _client.SendAsync(request))
{
var data = await response.Content.ReadAsStringAsync();
var code = response.StatusCode;
Console.WriteLine(Convert.ToString(code));
// do something with data
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.Assert(condition: false, message: ex.Message);
}
Console.WriteLine("End Put()");
}
Now, if I run the code it will break and show what the problem is.
Use the Exception Settings window to turn on all exceptions (if in doubt). Now the code will break on the exact line that is the problem.
Verify that you are Setting Authorization Header of HttpClient correctly as this may be part of the root cause of the exception.
Finally, if you continue after the Debug.Assert you will see the following text in your console which will confirm whether your Put method has had a chance to complete or not.
Hope these suggestions help you solve this problem and future ones!
// This workaround for C# versions below 7.1 attempts to
// mimic an `async Main` method.
static void Main(string[] args)
{
RunAsync();
Console.ReadKey();
}
private static async void RunAsync()
{
YourClient client = new YourClient();
// Put() should be awaited inside an async method
await client.Put();
}

.NET Core GetFromJsonAsync exits with no error or debugging information

I am trying to debug a request by GetFromJsonAsync which is supposed to fetch data from a Flask API and convert to JSON within a .NET Core cli app.
The issue I am having however is that after performing the request the cli app simply exits with no error. I have tried implementing try/catch block but nothing shows up there.
the Flask endpoint builds jsonifies a number of uuids and messages from Postgres and returns them to the client.
As GetFromJsonAsync is asynchronous I have tried making the Flask endpoint likewise but that has not seemed to help at all. The latter works fine and has been validated with curl.
I know the call executes as I can see it in my web server logs.
A similar call which simply returns plain javascript object {"foo": "bar"} works fine which is why I think this could by an async issue but I cannot see any errors etc to troubleshoot. I have placed a breakpoint on the foreach after the call but this is never hit.
What am I missing here?
public static async void GetMessages()
{
ConfigureHeaders();
try
{
var client = Client;
var res = await Client.GetFromJsonAsync<Received>(Url + "/api/chat/message"); // stops here
foreach (var c in res!.messages) // breakpoint here is never hit
Console.WriteLine(c);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public class Received
{
public Dictionary<string,string> messages { get; set; }
}
Flask
#message.get("/api/chat/message")
#csrf.exempt
async def get_messages():
new_msgs = {}
msgs = await get_unreplied() # DB gets called from another function here
try:
for m in msgs:
new_msgs[m.id] = m.message
if len(new_msgs) != 0:
return jsonify(new_msgs)
else:
return jsonify("no messages")
except Exception as e:
print(str(e))
This returns...
{
"id_foo1": "message_bar1",
"id_foo2": "message_bar2"
}
Best guess: your Main function is not awaiting the call to GetMessages
public async Task<int> Main(string []args)
{
await GetMessages();
}

Sending a POST request with retry using HTTPClient

So I've been searching like a mad man after a way to solve this issue, but I can't seem to find an answer.
So, I need to send a POST request with HTTPClient in C# to a server, and if the server isn't running it will keep sending the request until it connects (or dies after a nr of attempts). But I always get the exception System.Net.Http.HttpRequestException, which wouldn't be a problem if I just could store it (or something) and try again.
I found a couple of ways that people tried to do this, and I've tried them all. Creating a for-loop that loops and catches the exception that the program throws, adds to the counter and tries again. Creating a while-loop that loops until the HttpResponseMessage.IsSuccessStatusCode == true. I've even gone to such lengts as restarting the program if it can't connect (yeah, I'm that desperate).
So, I had to see if anyone of you guys might have a solution to this problem, or if you maybe had a better way to solve this problem.
Here is the code im running, thanks for your help!
EDIT: Just to add some clarity, the exception is thrown at the "rep"-variable, and the code never runs further than to that variable. And I've tried to make the HTTPResponseMessage variable just a "var" and await the Postasync method to.
HttpResponseMessage rep = new HttpResponseMessage();
try
{
rep = client.PostAsync("https://localhost:9999/", content).Result;
}
catch (Exception e)
{
}
Task t1 = Task.Factory.StartNew(() => ContinueTrasmission(client, c1.name, c1.state));
You have to look for retry libraries, for example Polly
var policy = Policy
.Handle<HttpRequestException>()
.WaitAndRetry(_retryCount, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
policy.Execute(() => DoSomething());
A solution could be:
bool success = false;
while (!success)
{
var rep = new HttpResponseMessage();
try
{
rep = client.PostAsync("https://localhost:9999/", content).Result;
//No exception here. Check your condition and set success = true if satisfied.
}
catch (Exception e)
{
//Log your exception if needed
}
}

VS2017 doesn't give details for an exception, just crashed with null

I'm working on a UWP project and there's something funky going on with how errors are being presented to me. I don't know if it's VS2017 or how UWP is set up.
I have a piece of code that goes online and retrieves json content, sometimes the code works and sometimes it doesn't. It works when I use Expander control from UWP Community toolkit, and fails when I want to switch to GridView. When it doesn't work, it fails on GetStringAsync method of HttpClient. The strange behavior is that the exception isn't thrown in the method where the problem occurs, the code actually redirects me back without giving an error and as soon as it gets to the property that's supposed to have a value that isn't null, I get a null exception.
This is where the problem happens:
string httpContent = "";
using (HttpClient httpClient = new HttpClient())
{
try
{
httpContent = await httpClient.GetStringAsync(uri);
}
catch (Exception e)
{
// TODO: handle errors
var x = "";
}
}
This piece of code is called from within the view model. It starts with a constructor and RefreshServerKanesWrathDataAsync is the method where json is parsed.
public CncOnlinePageViewModel()
{
cnconline = new CncOnline();
cnconline.RefreshServerKanesWrathDataAsync();
}
The second I get to GetStringAsync, the code just goes back to the constructor like nothing happened, however the method never completes, it just exits back to the constructor, and therefore fails to update observable collections with data. I then get a null exception.
I wanted to test this with VS2015, but I updated some controls that are apparently only supported withing VS2017, so I can't run the code in other versions.
I also ran into an issue with the code prior to this problem, where I tried to access files in a directory without using a token. The behavior was exactly the same, the code wasn't telling me that I didn't have access to the directory I wanted to read, it was just throwing me out of the method back into the location that made the call to read the directory. Just like with the current problem, I would then run into a null exception, which wasn't where the main problem was.
I added Template10 and UWP community toolkit to the project, if that matters.
You shouldn't call an async method from a constructor unless you're willing to provide a callback.
public CncOnlinePageViewModel()
{
cnconline = new CncOnline();
var t = cnconline.RefreshServerKanesWrathDataAsync(); // assuming returns Task<string>
t.ContinueWith(OnCompleted);
}
private void OnCompleted(Task<string> task)
{
if (task.IsFaulted)
{
// Check error
var exception = task.Exception;
}
else if (task.IsCanceled)
{
// User hit cancel?
}
else
{
// All good!
var result = task.Result;
}
}
Here's a sample where RefreshServerKanesWrathDataAsync() returns just Task (not Task<result>)
public CncOnlinePageViewModel()
{
cnconline = new CncOnline();
var t = cnconline.RefreshServerKanesWrathDataAsync(); // assuming returns Task
t.ContinueWith(OnCompleted);
}
private void OnCompleted(Task task)
{
if (task.IsFaulted)
{
// Check error
var exception = task.Exception;
}
else if (task.IsCanceled)
{
// User hit cancel?
}
else
{
// All good!
}
}
On a side note, you may also need to have Visual Studio 2017 break when any exception is thrown. In VS2017, go to Debug->Windows->Exception Settings and make sure Common Language Runtime Exceptions has a check. If it has a filled box, click the box until it turns into a checkmark.
Also..., you can tap into an event raised when any task has an unobserved exception. You can do so in the constructor of App.xaml.cs
public App()
{
TaskScheduler.UnobservedTaskException += OnUnobservedException;
}
private static void OnUnobservedException(object sender, UnobservedTaskExceptionEventArgs e)
{
// Put break point here.
var ex = e.Exception;
// This will keep your app alive, but only do it if it's safe to continue.
e.SetObserved();
}

HttpClient.GetAsync immediately throws TaskCanceledException

I had a working code that was returning something from my CommonRestClient(which is simple wrapper for HttpClient):
public async Task<IActionResult> Index()
{
var uri = _baseUri.Concat(AvalancheServiceAdresses.NodeService);
using (var client = new CommonRestClient(uri))
{
var result = await client.GetAsync<List<NodeInfoContract>>(new Uri(NodeServiceConstant.NodesContractUrl, UriKind.Relative), null);
return View(result);
}
}
It worked fine and i was happy. Until I decide to move my code from view in another class, which should incapsulate entire REST logic and provide an OOP API.
So now my index looks like:
public async Task<IActionResult> Index()
{
var nodeInfoContracts = await _configManager.GetNodesList();
return View(nodeInfoContracts);
}
where GetNodesList is
public ConfiguredTaskAwaitable<List<NodeInfoContract>> GetNodesList()
{
var uri = _baseUri.Concat(AvalancheServiceAdresses.NodeService);
using (var client = new CommonRestClient(uri))
{
return client.GetAsync<List<NodeInfoContract>>(new Uri(NodeServiceConstant.NodesContractUrl, UriKind.Relative), null);
}
}
It's clear that provided codes are equal.
But now it always throws an exception when I try to get a result. In my GetAsync method it fails on following line with TaskCanceledException:
var response = await _client.GetAsync(url).ConfigureAwait(false);
But it's interestring: when I place a breakpoint on this line and step over its works fine. So here we have race condition or similar.
Why am I getting it? I tried to place CondigureAwait false/true, combining some code, but it always throws an error when breakpoints are off. I checked timeout which is several minutes, it can't cause this error.
In the second code snippet the client is disposed before the IO completed. Use the first form.

Categories

Resources