Is there any way to stop the UI window instance of WPF - c#

When I'm sending the data on a server and server is not up then I get an exception Unable to connect to the server and the UI window instance is closed while executing the line of code :
(response = await client.PostAsJsonAsync("windows/actions", data).ConfigureAwait(false);). How can I stop the UI window it should not be closed.
My code :
public static async void PostInfo(List<ElementProps> requestObj)
{
try
{
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
// Setting Base address.
client.BaseAddress = new Uri("http://126.1.1.1:8888/");
// Setting content type.
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
string list = JsonConvert.SerializeObject(requestObj);
object data = JsonConvert.DeserializeObject(list);
// HTTP POST ** Here is the error **
response = await client.PostAsJsonAsync("windows/actions", data).ConfigureAwait(false);
// Verification
if (response.IsSuccessStatusCode)
{
System.Windows.MessageBox.Show("Recording saved successfully!"); <br/>
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
ErrorLog.Log(ex);
}
}

My main thread exits before the http client async operation finishes.
I just add .Wait() to caller to maintain the main thread. So, I have this :
PostInfo(Records).Wait();

Related

Close HttpListener only after a response is finished

I need to implement a simple HTTP server using the HttpListener which redirects the browser to another web (after visiting http://127.0.0.1:8080) and then self-closes (after a successful response). I implemented it in this way:
var httpListener = new HttpListener();
try
{
httpListener.Prefixes.Add("http://127.0.0.1:8080/");
httpListener.Start();
var context = await httpListener.GetContextAsync();
context.Response.Redirect("https://stackoverflow.com/");
context.Response.Close();
}
catch (Exception ex)
{
// ...
}
finally
{
httpListener?.Close();
}
but it doesn't work very reliably - in ~50% of cases my browser ends up with "ERR_CONNECTION_REFUSED". It seems, that httpListener.Close() is called before the request is finished, so the browser loses the connection while receiving the HTTP data. I didn't find any way/callback to get notified when the request is fulfilled, so I can close the listener safely. I ended up with a workaround by adding the await Task.Delay(1000); before closing the HTTP listener, which works fine and my browser is always redirected:
var httpListener = new HttpListener();
try
{
httpListener.Prefixes.Add("http://127.0.0.1:8080/");
httpListener.Start();
var context = await httpListener.GetContextAsync();
context.Response.Redirect("https://stackoverflow.com/");
context.Response.Close();
await Task.Delay(1000); // Ugly workaround
}
catch (Exception ex)
{
// ...
}
finally
{
httpListener?.Close();
}
Is there a more elegant way to automatically close the HttpListener and be sure, that the request has been fulfilled?

httpClient.GetAsync() timeout exception, if application idle a long time

I developed C# .net 4.6.1 application.
In the application I use HttpClient for communicate with our backend API.
Over time the application not sending the request to our backend (timeout exception is catched). The request is sent, after restart application.
Here is the snippet of our code.
class Program
{
static void Main(string[] args)
{
MyClass myClass = GetAsync().Result;
}
private static async Task<MyClass> GetAsync()
{
MyClassResponse myClassResponse = await TestHttpClient.GetMyClassResponse();
return MyClass.Create(myClassResponse);
}
}
public static class TestHttpClient
{
private static HttpClient _httpClient;
public static void Init()
{
_httpClient = CreateHttpClient();
}
public static async Task<MyClassResponse> GetMyClassResponse()
{
HttpResponseMessage response = await GetRequestAsync("https://....");
return await ParseToMyClassResponse<MyClassResponse>(response);
}
private static HttpClient CreateHttpClient()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token .....");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.Timeout = TimeSpan.FromMilliseconds(10000);
return client;
}
private static async Task<HttpResponseMessage> GetRequestAsync(string url)
{
try
{
return await _httpClient.GetAsync(new Uri(url));
}
catch (TaskCanceledException)
{
return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
}
}
private static async Task<T> ParseToMyClassResponse<T>(HttpResponseMessage response) where T : MyClassResponse, new()
{
T myClassResponse;
try
{
string content = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
myClassResponse = JsonConvert.DeserializeObject<T>(content);
}
catch (Exception ex)
{
myClassResponse = new T();
}
response.Dispose();
return myClassResponse;
}
}
What am I doing wrong?
A couple things I see:
First, your exception handler is ignoring the exception and throwing a new exception. Assign a variable to your TaskCanceledException and log that actual exception before you throw a new one. The inner exceptions might give you more information about what happened.
catch (TaskCancelledException e))
{
Debug.WriteLine(e);
//do whatever else
}
Side note: using new HttpResponseMessage(HttpStatusCode.RequestTimeout) is probably not the most appropriate thing. That makes it look like the server returned a 408 Request Timeout. When that's not really what happened.
A timeout that would throw a TaskCanceledException is when the client sent the request, but no response was received from the server in the time expected (30 seconds by default).
If that's truly the kind of timeout happening, then you may have to look at something like Wireshark or Fiddler to verify that the request is actually being sent. Then you would have to figure out what's different between that request and the request sent once you restart the application.
For example, is your token expired and restarting your application requests a new one? (that shouldn't result in a timeout, but if the server code is poorly written it could)
I added logging and got following error:
System.Threading.Tasks.TaskCanceledException ยท A task was cancelled.
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
TestHttpClient+<GetRequestAsync>d__20.MoveNext()
And I looked at the requests with using Fiddler, and got following results
In normal mode fiddler shows 2 requests
Result=200, Protocol=HTTP, Host = Tunnel to, Url = api.example.com:443
in SyntaxView tab: A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.
Result=200, Protocol=HTTPS, Host = api.example.com, Url = /test
In failed mode Fiddler shows only 1 requst
Result=200, Protocol=HTTP, Host = Tunnel to, Url = api.example.com:443,
in SyntaxView tab: After the client received notice of the
established CONNECT, it failed to send any data
I would like to make a correction. In reality, I use the Init() method like this.
public static class TestHttpClient
{
private static HttpClient _httpClient;
public static void Init()
{
ServicePointManager.SecurityProtocol |= (SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls);
ServicePointManager.DefaultConnectionLimit = 10;
_httpClient = CreateHttpClient();
}
}

How to post data using HttpClient? (an answer than actually works)

There is another question about this, but it doesn't have a functioning solution at the end, and the only good answer, for some reason, doesn't work, not for the guy who ask it, not for me either.
This such question is here:
How to post data using HttpClient?
Given the corresponding aclarations, this is the code I have so far:
The methods to call the method who connects with the web server:
private void Button_Click(object sender, System.EventArgs e)
{
//. . . DO SOMETHING . . .
PopulateListView();
//. . . DO SOMETHING ELSE . . .
}
private void PopulateListView()
{
//. . . DO SOMETHING . . .
list = await "http://web.server.url".GetRequest<List<User>>();
//. . . DO SOMETHING ELSE . . .
}
The method than connects with the web server:
public async static Task<T> SendGetRequest<T>(this string url)
{
try
{
var uri = new Uri(url);
HttpClient client = new HttpClient();
//Preparing to have something to read
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("OperationType", "eaf7d94356e7fd39935547f6f15e1c4c234245e4")
});
HttpResponseMessage response = await client.PostAsync(uri, formContent);
#region - - Envio anterior (NO FUNCIONO, SIN USO) - -
//var stringContent = new StringContent("markString");
//var sending = await client.PostAsync(url, stringContent);
//MainActivity.ConsoleData = await client.PostAsync(url, stringContent);
#endregion
//Reading data
//var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
MainActivity.ConsoleData = json.ToString();
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
}
catch(Exception ex)
{
Console.WriteLine("Error: "+ex.ToString());
return default(T);
}
}
You maybe guessed it, but I'm trying to make a method that send some data (through POST) called "markString" to a web-server than receive it and, depending of the "markString" it returns certain json Objects.
This web server is already working properly (I tested it out with some plug-in, it work like it should)
This method is supposed to send the "markString" and receive the data back so then i can use it in the app.
I'm making a Xamarin Android application.
Also have in mind than I don't have any connection problem at all, in fact the app is sending data in an excellent matter when I try to do it using web client, but I want it to send it using HttpClient.
The problem
The code is not returning anything. Any request for information, clarification, question, constructive comments or anything than can lead to an answer would be greatly appreciated too.
Thanks in advance.
Most deadlock scenarios with asynchronous code are due to blocking further up the call stack.
By default await captures a "context" (in this case, a UI context), and resumes executing in that context. So, if you call an async method and the block on the task (e.g., GetAwaiter().GetResult(), Wait(), or Result), then the UI thread is blocked, which prevents the async method from resuming and completing.
void Main()
{
var test = SendGetRequest("http://www.google.com");
test.Dump();
}
public async static Task<string> SendGetRequest(string url)
{
try
{
var uri = new Uri(url);
HttpClient client = new HttpClient();
//Preparing to have something to read
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("OperationType", "eaf7d94356e7fd39935547f6f15e1c4c234245e4")
});
HttpResponseMessage response = await client.PostAsync(uri, formContent);
#region - - Envio anterior (NO FUNCIONO, SIN USO) - -
//var stringContent = new StringContent("markString");
//var sending = await client.PostAsync(url, stringContent);
//MainActivity.ConsoleData = await client.PostAsync(url, stringContent);
#endregion
//Reading data
//var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
return json;
}
catch (System.Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
return string.Empty;
}
}

C# HttpClient to post information without waiting for response

I am using HttpClient class in my asp.net web api 2 application to post some information to a endpoint. I just want to post the information without waiting for a response. Is this the right syntax
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:9000/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP POST
var gizmo = new Product() { Name = "Gizmo", Price = 100, Category = "Widget" };
var response = await client.PostAsJsonAsync("api/products", gizmo);
}
I just want to post the information without waiting for a response
Not awaiting an async method in WebAPI will result in a runtime exception, as the AspNetSynchronizationContext is aware of any triggered asynchronous operations. If it notices a controller action completes before the async operation has, it will trigger the said exception. More on that in ASP.NET Controller: An asynchronous module or handler completed while an asynchronous operation was still pending
If you want to use a fire and forget semantics, you need to queue the delegate via HostingEnvironment.QueueBackgroundWorkItem if you're using .NET 4.5.2 and above. If not, you can defer to using BackgroundTaskManager
Keep in mind this kind of design isn't really suitable for WebAPI. It doesn't scale if you're triggering this action call frequently. If this style happens often, consider using something more suitable such as a message broker.
To implement the async Task in ASP.NET refer to the following sample syntax:
protected void Page_Load(object sender, EventArgs e)
{
try
{
RegisterAsyncTask(new PageAsyncTask(LoadUrlContent));
}
catch {}
}
protected async Task LoadUrlContent()
{
try
{
// Add your code here, for example read the content using HttpClient:
string _content = await ReadTextAsync(YourUrl, 10);
}
catch { throw; }
}
Also, set <%# Page ... Async="true" %> at page level.
Following sample code snippet shows the use of HttpClient (call this sample function from LoadUrlContent():
protected async Task<string> ReadTextAsync(string Url, int TimeOutSec)
{
try
{
using (HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromSeconds(TimeOutSec) })
{
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/html"));
using (HttpResponseMessage _responseMsg = await _client.GetAsync(Url))
{
using (HttpContent content = _responseMsg.Content)
{
return await content.ReadAsStringAsync();
}
}
}
}
catch { throw; }
}
You can modify this code base pertinent to your particular task.
Hope this may help.

How to close a soap client while making async calls?

I am calling a soap service asynchronously but stuck at a point where I need to close a soap client connection. Not much help from previous post either: How to close Client Proxy with Async Call WCF
Below is my code so far.
Method below (GetFieldList(....) calls generic method ApiClient.GetResponse(....) with request parameters and what service to invoke
public async Task<ServiceReference.GetFieldListResponse> GetFieldList(string identifier)
{
var request = new GetFieldListRequest
{
Header = new Header {Username = ApiSettings.Instance.ApiToken},
AGroup = "",
IdType = "",
Id = ""
};
var response = await ApiClient.GetResponse(request, (c) => c.GetFieldListAsync(request.Header, request.Id, request.IdType, request.AGroup));
return response;
}
In the method below, I have commented out finally block because the connection was being closed before a response was returned to the calling method.
public class ApiClient
{
public static TResponse GetResponse<TResponse, TRequest>(TRequest request,
Func<SoapClient, TResponse> handler,
string apiMethodName = "")
where TResponse : class
{
Debug.WriteLine("Calling: " + typeof(TRequest).Name);
if (string.IsNullOrEmpty(apiMethodName))
{
apiMethodName = typeof(TRequest).Name.Replace("Request", string.Empty);
}
// creates a soap connection
var client = WebServiceClient.CreateServiceInstance();
TResponse response = null;
try
{
//webservice call is invoked here
response = handler(client);
}
catch (FaultException exception)
{
throw new ApiException(string.Format("Api error on {0}.", apiMethodName), exception);
}
//if this finally block is not commented, connection is closed before a response was returned to the calling method.
//finally
//{
// client.Close();
//}
return response;
}
}
Any idea what am I missing?
Thanks
I would suggest to have a global WebServiceClient or ApiClient, and do GetResponse and CloseClient in two threads. That way, even you are waiting for response, you can force trigger client close in CloseClient thread.

Categories