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.
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 have ASP.NET Core 2.1 application hosted on Azure web app. I am sending photos base64 string over WebSockets and then by HttpClient to Azure Face API.
After some 150-250 requests HttpClient stops responding and I can't use HttpClient class in any part of my application.
In my localhost it works properly and I never get this problem.
public class FaceApiHttpClient
{
private HttpClient _client;
public FaceApiHttpClient(HttpClient client)
{
_client = client;
}
public async Task<string> GetStringAsync(byte[] byteData,string uri)
{
using (ByteArrayContent content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
HttpResponseMessage response = await _client.PostAsync(uri, content).ConfigureAwait(false);
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
DI:
services.AddHttpClient<FaceApiHttpClient>(
client => {
client.BaseAddress = new Uri("xxx");
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "xxx");
});
The method from FaceApiClient is invoke in a Scoped Service:
public interface IFaceAPIService
{
Task<DataServiceResult<List<Face>>> GetFacesDataFromImage(byte[] byteArray);
}
public class FaceAPIService: ServiceBase, IFaceAPIService
{
private readonly IServerLogger _serverLogger;
private FaceApiHttpClient _httpClient;
//Consts
public const string _APIKey = "xxx";
public const string _BaseURL = "xxx";
public FaceAPIService(IServerLogger serverLogger, FaceApiHttpClient client)
{
_serverLogger = serverLogger;
_httpClient = client;
}
public async Task<DataServiceResult<List<Face>>> GetFacesDataFromImage(byte[] byteData)
{
try
{
// Request parameters. A third optional parameter is "details".
string requestParameters = "returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise";
// Assemble the URI for the REST API Call.
string uri = _BaseURL + "/detect" + "?" + requestParameters;
var result = await _httpClient.GetStringAsync(byteData, uri).ConfigureAwait(false);
List<Face> faces = JsonConvert.DeserializeObject<List<Face>>(result);
return Success(faces);
}
catch (Exception ex)
{
_serverLogger.LogExceptionFromService(ex);
return DataServiceResult.ErrorResult<List<Face>>(ex.Message);
}
}
}
a) on localhost enviroment it works. I run 11 simulators with many request per seconds and it never broke (10 hours of simulators, over 20k requests).
b) HttpClient stops working in any part of application not only in one class.
How to fix this?
Consider changing up the design a bit.
Using a typed client the assumption is that its configuration is something that will not change frequently and that it should be added once when registering the typed client.
services.AddHttpClient<FaceApiHttpClient>(_ => {
_.BaseAddress = new Uri(Configuration["OcpApimBaseURL"]);
var apiKey = Configuration["OcpApimSubscriptionKey"];
_.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
_.Timeout = new TimeSpan(0, 0, 10);
});
Which would allow the typed client to no have to add the key for every call
public class FaceApiHttpClient {
private readonly HttpClient client;
public FaceApiHttpClient(HttpClient client) {
this.client = client;
}
public async Task<string> GetStringAsync(byte[] byteData, string uri) {
using (var content = new ByteArrayContent(byteData)) {
// This example uses content type "application/octet-stream".
// The other content types you can use are "application/json" and "multipart/form-data".
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
// Execute the REST API call.
HttpResponseMessage response; response = await _client.PostAsync(uri, content).ConfigureAwait(false);
// Get the JSON response.
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
It should be noted from ASP.NET Core 2.1-preview1: Introducing HTTPClient factory
A typed client is, effectively, a transient service, meaning that a new instance is created each time one is needed and it will receive a new HttpClient instance each time it is constructed. This means that the configuration func, in this case retrieving the URI from configuration, will run every time something needs a FaceApiHttpClient.
Based on previous documentations, having that many clients created can pose problems, but the assumption here is that the developers of this new feature took that into consideration when designing it.
I say this because the issues you described are similar to previous problem with the same cause.
After release version of ASP .NET CORE 2.1 RC1 the problem is fixed. I updated project to new version and now there is no problem with deadlock.
The problem with deadlock was only in ASP .NET CORE 2.1 Preview 2 version.
I have the following cURL command which works properly to get the data i need and I am trying to call this API from within my C# code.
curl "https://api.propublica.org/congress/v1/members/senate/RI/current.json" - H "X-API-Key: <MyAPIKey>"
I have written the following code in C# to try calling this API.
class Program
{
static HttpClient client = new HttpClient();
static void Main()
{
var listing = GetCongressmanByState("IL");
Console.ReadLine();
}
static async Task<List<Congressman>> GetCongressmanByState(string State)
{
string apiurl = "https://api.propublica.org/congress/v1/members/senate/" + State + "/current.json";
string apikey= "<MyAPIKey>";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("X-API-Key", apikey);
HttpResponseMessage response = await client.GetAsync(apiurl);
if(response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
var rootResult = JsonConvert.DeserializeObject<RootObject>(result);
return rootResult.congressmen;
}
else
{
return null;
}
}
}
Trying to step through the GetCongressmanByState the program seems to jump over my if statements and right back to the main function.
When i run with a breakpoint at console.readline() this is what is within listing:
listing contents
Is there an issue with my code?
I am calling a test REST web service that basically takes a string as input, and echoes it back to the caller. I have the following code, in a C# console app:
static async Task RunAsync()
{
using (var client = new HttpClient())
{
string baseAddress =
"http://xxx.xxx.xxx.xxx/Services/OnyxCloudSyncService.svc/pingSync";
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await
client.GetAsync("?sampleJson={SAMPLEJSON}");
if (response.IsSuccessStatusCode)
{
string txtBlock = await response.Content.ReadAsStringAsync();
Console.WriteLine(txtBlock);
Console.ReadKey();
}
}
}
This code runs perfectly. But when I essentially copy the same code into the code-behind for an ASP.NET page, I timeout on the call to the service:
using (var SyncClient = new HttpClient())
{
string baseAddress = "http://xxx.xxx.xxx.xxx/Services/OnyxCloudSyncService.svc/pingSync";
SyncClient.DefaultRequestHeaders.Accept.Clear();
SyncClient.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await
SyncClient.GetAsync("?sampleJson={SAMPLEJSON}");
if (response.IsSuccessStatusCode)
{
string txtBlock = await response.Content.ReadAsStringAsync();
Response.Write(txtBlock);
Response.End();
}
else
{
Response.Write("Error Calling service");
Response.End();
}
}
The error I get from this page is:
System.Net.Sockets.SocketException: A connection attempt failed because
the connected party did not properly respond after a period of time, or
established connection failed because connected host has failed to respond
xxx.xxx.xxx.xxx:80.
Would there be some type of setup or option I need to set on the WebClient to make it work in the ASP page like it does in the Console App? I am at a loss as to why this would work in a console app and not in an ASP.NET web page.
You might be having a problem because the result is not being waited for, the solution might be found on: http://www.hanselman.com/blog/TheMagicOfUsingAsynchronousMethodsInASPNET45PlusAnImportantGotcha.aspx
I assume you're using .NET 4.5.
Edit method to be instance, not static since you won't be able to reach Response object:
async Task RunAsync()
{
using (var client = new HttpClient())
{
string baseAddress =
"http://74.120.219.166/Services/OnyxCloudSyncService.svc/pingSync";
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await
client.GetAsync("?sampleJson={SAMPLEJSON}");
if (response.IsSuccessStatusCode)
{
string txtBlock = await response.Content.ReadAsStringAsync();
Response.Write(txtBlock);
Response.End();
}
else
{
Response.Write("Error Calling service");
Response.End();
}
}
}
Run method like: RegisterAsyncTask(new PageAsyncTask(RunAsync));
Put Async="true" in Page directive of your .aspx page.
I tried this approach and it worked as expected.
I have some very simple code that I have been using in a windows 8 store app without any issue. However When I shared the code with windows phone app It just hangs forever. See sample below. This calls any web url and returns its source as a string. both the post and get methods hang in the same way. any help is much appreciated, Thank you.
public static string GetWebSource(string Url)
{
HttpClient client = new HttpClient();
Task<HttpResponseMessage> Resp = client.GetAsync(Url);
//code hangs on following line forever
//Resp.status always stays at waiting for activation
Task.WaitAll(Resp);
if (Resp.Result.IsSuccessStatusCode)
{
Task<string> response = Resp.Result.Content.ReadAsStringAsync();
Task.WaitAll(response);
return response.Result;
}
return "";
}
public static string PostWebSource(string Url, string data)
{
HttpClient client = new HttpClient();
StringContent sc = new StringContent(data);
Task<HttpResponseMessage> Resp = client.PostAsync(Url, sc);
//code hangs on following line forever
//Resp.status always stays at waiting for activation
Resp.Wait();
if (Resp.Result.IsSuccessStatusCode)
{
Task<string> response = Resp.Result.Content.ReadAsStringAsync();
Task.WaitAll(response);
return response.Result;
}
return "";
}
You should be using an HttpWebRequest on Windows Phone. See this link: http://social.msdn.microsoft.com/Forums/wpapps/en-us/9b4c1ef2-853c-468a-bca8-97477a02583c/httpclient-for-windows-phone-8?forum=wpdevelop