I'm trying to call a webapi from a console application (which is triggered by windows task scheduler). I don't want my console app to wait for the result from api.I just want to call api and initiate it and exit the console application.
My console application code is
public static void InvokeSisService(string feature)
{
var serviceurl = ConfigurationManager.AppSettings["AppServiceURL"];
var controllerPath= ConfigurationManager.AppSettings["ControllerPath"];
var client = new HttpClient { BaseAddress = new Uri(serviceurl) };
controllerPath= controllerPath+ "?feature=" + feature;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
//client.PostAsync(smsservicepath, null);
// var temp=client.GetAsync(smsservicepath).Result;
var response = Task.Run(() => client.GetAsync(controllerPath)).Result;
}
My webapi is being called but it was waiting for the output.How do i exit console app after calling api.
Webapi code
[HttpGet]
[Route("ProcessService")]
public HttpResponseMessage ProcessService([FromUri] string feature)
{
}
I'm sure you want to make sure the response was received, so change
var response = Task.Run(() => client.GetAsync(controllerPath)).Result;
To:
using (var response = await client.GetAsync(controllerPath, HttpCompletionOption.ResponseHeadersRead))
This will drop after the response headers have been received. This does NOT include error handling - you should probably add error handling to the mix to make sure you are getting a proper response code before moving on - but that's up to you.
var response = Task.Run(() =>
client.GetAsync(controllerPath)).Result;
with the property "Result" you are waiting for the Response.
Related
I am working on a Xamarin.Forms multi-platform app, which shall utilize a custom Asp.Net Core Web Api. I've written the code to make the calls to the API, but it fails on Android.
I am suspecting some kind of SSL issue... but we'll get to that in a second.
I am using HttpClient and HttpClient.PostAsync for the calls and on Android - and only on Android - it comes to an deadlock on the PostAsync.
I therefore created a minimum example and started from the beginning:
HttpClient client = new HttpClient();
return client.GetAsync("https://www.google.com").Result.Content.ReadAsStringAsync().Result;
Is working fine, then I tried it with my domain, which contains a simple Asp.Net page, which also worked:
HttpClient client = new HttpClient();
return client.GetAsync("https://aircu.de").Result.Content.ReadAsStringAsync().Result;
Next step was to try and address my API:
HttpClient client = new HttpClient();
var response = client.GetAsync("https://api.aircu.de").Result;
return response.Content.ReadAsStringAsync().Result;
This now fails on Android, the line var response = client... never returns. However it is working on iOS and (in a testing .net core console application) on windows, too. If i add a timeout to the client, the application of course will run into that timeout and throw an exception.
I've tried using async Task<string> and var response = await client.GetAsync("https://api.aircu.de").ConfigureAwait(false);, didn't work either...
I cannot find the problem; I've tried adding a custom handler for the server certificates, which did not help. I added Accept for the client and MediaType for a string content I added; didn't work either.
I've changed the Android HttpClientImplementation to Standard, Legacy and Android; didn't change a thing.
What do I need to do, to make this request working on Android?
EDIT://
To make it crystal clear: There is no deadlock issue! When I use any other url, like my base-url https://aircu.de it's working fine. The function only does not return, when using the subdomain https://api.aircu.de
I also moved my demo code to a VM...
private HttpClient client = null;
public MainPageViewModel()
{
client = DependencyService.Get<IHttpsClientFactory>().CreateClient();
client.Timeout = TimeSpan.FromSeconds(5);
}
[RelayCommand]
public void Click()
{
Task.Factory.StartNew(requestTaskFn);
}
private async void requestTaskFn()
{
var result = await makeRequest();
Device.BeginInvokeOnMainThread(async () => await Application.Current.MainPage.DisplayAlert("Result", result, "OK"));
}
private async Task<string> makeRequest()
{
string responseJson = "";
try
{
var response = await client.GetAsync("https://api.aircu.de").ConfigureAwait(false);
responseJson = await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
throw;
}
return responseJson;
}
I also added an AndroidClientHandler in the IHttpsClientFactory:
var handler = new AndroidClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
return new HttpClient(handler);
I am using Xamarin.Forms and I am using HttpClient GetAsync and PostAsync to make calls to an api, my problem is the client is complaining that the application is too slow when it makes an api call. Is there anyways I can speed up this process or is there another faster way to call an api? Here is an example method:
public async Task<List<SubCatClass>> GetSubCategories(int category)
{
var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("category", category.ToString())
});
var response = await client.PostAsync(string.Format("https://exmample.com/api/index.php?action=getSubCategories"), content);
var responseString = await response.Content.ReadAsStringAsync();
List<SubCatClass> items = JsonConvert.DeserializeObject<List<SubCatClass>>(responseString);
return items;
}
And here is how I am calling it.
await webService.GetSubCategories(item.categoryid);
The api I have full control over the code (PHP) and the server.
Any help would be much appreciated.
Thanks in advance.
UPDATE
I called the api in postman and here was the results
You can try using ModernHttpClient, it will increase your speed than using default by Xamarin
I am facing an issue regarding not getting response from GetAsync API of HttpClient in MVC Applications(Target Framework - .Net Framework 4.7) whereas getting response in web services and console applications with same snippet. Here I have attached code snippet which I am trying to execute.
public void Get()
{
var response = Gettasks().Result;
}
public static async Task<HttpResponseMessage> GetTasks()
{
var response = new HttpResponseMessage();
try
{
using (var client = new HttpClient())
{
response = await client.GetAsync("https://www.google.com");
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
return response;
}
I am getting stuck on response = await client.GetAsync("https://www.google.com"); this line and not getting any response after executing this statement.
If anyone can please suggest solution for this or provide fix/solution which works for you.
You're seeing a deadlock because the code is blocking on an asynchronous method.
The best fix is to remove the blocking:
public async Task Get()
{
var response = await Gettasks();
}
This deadlock happens because await captures a context, and ASP.NET (pre-Core) has a context that only allows one thread at a time, and the code blocks a thread (.Result) in that context, which prevents GetTasks from completing.
Both the context and the blocking are necessary to see this kind of deadlock. In the other scenarios, there is no context, so that is why the deadlock does not occur. Since ASP.NET (pre-Core) has a context, the proper solution here is to remove the blocking.
Not sure whether you have tried following which is working for me.
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(Environment.GetEnvironmentVariable("BaseAddress"));
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var requestUri = Environment.GetEnvironmentVariable("Uri");
HttpResponseMessage response = await client.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
}
}
I am trying to learn some docker, i managed to setup API image/container and it works fine, I can get response from the API when i'll go through web browser. However my console client can't get a request to my API and I am not sure why. The only error i get is Cannot assign requested address in docker CLI.
class Program
{
static HttpClient client = new HttpClient();
static string apiUrl = "http://localhost:8080";
static void Main()
{
System.Console.WriteLine("Console started.");
RunAsync().GetAwaiter().GetResult();
}
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("http://localhost:64195/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
System.Console.WriteLine(client.BaseAddress);
try
{
var value = await GetValueAsync();
}
}
}
And the method that generate the error:
static async Task<Value> GetValueAsync()
{
Value value = null;
HttpResponseMessage response = await client.GetAsync(apiUrl + "/value");
System.Console.WriteLine("TEST");
if (response.IsSuccessStatusCode)
{
value = await response.Content.ReadAsAsync<Value>();
}
return value;
}
Program stops and returns an error on the client.GetAsync line, it never gets to the writeline("TEST"). Anyone knows what could be the problem? Everything else works until the request. On the request the Cannot assign requested address shows up and stops the container/program.
I have this code:
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{"site_id","001"},
{"apikey","abc01201az1024"},
{"trans_id","45364136"},
};
// Get the parameters in the url encoded format
var content = new FormUrlEncodedContent(values);
//Send request
var response = await client.PostAsync(url, content);
DataRoot<Transaction> outPut = null;
if (response.IsSuccessStatusCode)
{
//Get Response
var result = await response.Content.ReadAsStringAsync();
JsonConvert.DeserializeObject<DataRoot<Transaction>>(result);
}
return outPut;
}
In the debug mode at this stage, the code does not produce any response, no error code but stops running:
//Send request
var response = await client.PostAsync(url, content);
there could be a better way but this solved my problem. Call your method from another one using wait:-
public static async Task<string> AuthenticateUser()
{
var t = Task.Run(() => ClassObject.AuthenticateUser("me"));
t.Wait();
Console.WriteLine(t.Result);
Console.ReadLine();
return "ok";
}
Using await like this, can end up in a deadlock.
You can use ConfigureAwait(false) in async methods for preventing such a deadlock.
Update code to:
var response = await client.PostAsync(url, content).ConfigureAwait(false);
This will solve the issue.
Are you sure that it isn't actually returning the response and continuing execution? Because the client.PostAsync() call is awaited execution may continue on a different thread. Therefore, if you're just debugging line by line (via F10 or similar) it may appear that the method never returns; in actuality the entire method has finished execution and your program is running.
You may need to add another breakpoint in the method (after the PostAsync method call). When the PostAsync method returns on a different thread, your debugger should hit the next breakpoint.