SSIS C# HTTP GetAsync not waiting for the response - c#

I'm using the getAsync(URL).Result function inside an SSIS C# task. In the debug window I can see the Result="{Not yet computed}".
The code is working very well for the last 1 year, although stops working after a new release of the API came up. It seems it's not waiting for the response.
MY CODE:
public void Main()
{
GetRequest(Dts.Variables["User::URL"].Value.ToString());
Dts.TaskResult = (int)ScriptResults.Success;
}
private static void GetRequest(string url)
{
try
{
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
}
catch (Exception e)
{
System.Console.WriteLine("Caught Exception: " + e.Message);
}
}
Can someone give me some insights?
Thank you

Thank you #jdweng
Copy of the comment that helps me to solve the issue:
Sounds like a TLS authentication issue. Five years ago the industry decided to eliminate TLS 1.0/1.1 due to security issues. In June this year Microsoft pushed a security update disabling TLS 1.0/1.1 and now require clients to use TLS 1.2/1.3. So adding to your code following seems to solve issue : ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Related

HttpClient PostAsync does not return

I've seen a lot of question about this, and all points to me using ConfigureAwait(false), but even after doing so, it still doesn't returned any response. When I run the debugger, the code stops at the PostAsync and does not continue with my code. Am I doing something wrong here? Does it have to do with me calling an API via HTTPS?
Here's the code:
public async static Task<PaymentModel> AddAsync(Card card)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:", "hidden"))));
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
var cardJson = JsonConvert.SerializeObject(card);
var postRequest = new StringContent(cardJson, Encoding.UTF8, "application/json");
var request = await client.PostAsync(new Uri("https://sample-3rd-party-api/api/endpoint/here"), postRequest).ConfigureAwait(false);
var content = await request.Content.ReadAsStringAsync().ConfigureAwait(false);
}
EDIT:
In response to the comments below, the code is contained from a method AddAsync(Card card) called from a button click with a handler:
public async void OnExecute(object sender, EventArgs args)
{
//some code here
payment = await PaymentModel.AddAsync(card).ConfigureAwait(false);
}
EDIT 2:
I tried pinging the API, but it returns a request timed out, but when I tried it using Postman, it's doing fine (the API is just a Sandbox which is open for all, so it's okay to share this):
EDIT 3:
I think the problem lies with where I don't have an SSL certificate to access the API. I have a PHP server that connects to the same API and I have to set SSL_VERIFYPEER to false just so I can access it (don't worry, I added a cacert now so its on true again). Can the same issue be happening here? If so, what can I do to create a valid certificate for my xamarin forms app
You can use this
var json = JsonConvert.SerializeObject(card);
using (var client = new HttpClient())
{
var t = await client.PostAsJsonAsync("https://sample-3rd-party-api/api/endpoint/here", json);
Response R =JsonConvert.DeserializeObject<Response>((JsonConvert.DeserializeObject(t.Content.ReadAsStringAsync().Result.ToString())).ToString());
}
What's most likely happening here is your OnExecute method has a return type of void instead of Task which prevents the UI thread from being able to await it. Try either changing that return type to Task or creating a new UI thread to perform this work. I wouldn't worry about the ping timing out as long as Postman works. Many public web servers disable their ping response.
Does it have to do with me calling an API via HTTPS?
As you are remaining in the same network and calling the same API from POSTMAN and .NET HTTP Client and only getting success with POSTMAN.So this issue gets cancelled.
Next
tried pinging the API, but it returns a request timed out
This is answered on top of mine.
Can you Please try setting the timeout option for HTTPClient while initializing.
client.Timeout = TimeSpan.FromSeconds(10);
and if still Problem persists please setup Fiddler and compare both the req sent from POstman and .NET client
So I think the problem is resolved now since I'm able to receive content from the request, what I did was simply follow the docs here: https://learn.microsoft.com/en-us/xamarin/cross-platform/app-fundamentals/transport-layer-security?tabs=windows
It looks like my settings are outdated in platform level.
Update the HttpClient implementation and SSL/TLS implementation
options to enable TLS 1.2 security.
Update the HttpClient Implementation option to enable TSL 1.2
security. (NSUrlSession (iOS 7.0+)
I was having the same issue and below trick fixed the issue.
Change your var request = await client.PostAsync(...); as below
var task = client.PostAsync(new Uri("https://sample-3rd-party-api/api/endpoint/here"), postRequest);
var request = task.GetAwaiter().GetResult();

C# Mono ssl issue

Alright, I am using the following code:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback += (send, cert, chain, sslPolicyErrors) => true;
string dlclresponse = "";
try
{
WebRequest wr = WebRequest.Create(url);
Stream stream = wr.GetResponse().GetResponseStream();
Debug.WriteLine("HTTPDEBUG:" + " Success");
dlclresponse = new StreamReader(stream).ReadToEnd();
}
catch (WebException we)
{
var ex = we as Exception;
while (ex != null)
{
Debug.WriteLine("HTTPDEBUG:" + ex.ToString());
ex = ex.InnerException;
}
}
I am fully aware that this just neglects the security behind ssl, but I just can't seem to get this working on my Ubuntu server using mono.
The url that isn't working is the following:
https://atarashii.toshocat.com/2.1/anime/schedule
It keeps giving me this exception:
System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed.
I've read quit a bunch but honestly I don't understand much of it.
What am I doing wrong? Most of the answers found to this solution is something like the above, but it just keeps crashing. I tried multiple about everything from here:
Mono https webrequest fails with "The authentication or decryption has failed"
But none seemed to do anything ;(.
At the moment I am really lurking to use that curl hack since this just feels unsolvable at the moment.
I hope maybe one of you might have another idea which could help me out.
Thanks in advance!
Ok, stupid me. I actually had an older version of mono, 4.2.1.102 in fact. Which just didn't want to work with me. Removing that and updating to the latest version fixed it ;/. Bye bye hours wasted on finding the ultimate: did you reinstall it fix.

HttpClient request on non TLS 1.0

I am attempting to perform Post requests to a server in my Xamarin forms app, however we recently updated our security policies and are no longer using TLS 1.0 This change appears to have broken the post request and now it times out.
To test this we re-enabled TLS 1.0 just for this service, and I can confirm it does now work. We of course would prefer to force better ciphers, is there any adjustments that can be made to the following request that could ensure it works once we return to the previous policy.
public static async Task<LoginResponse> LoginRESTSend(FormUrlEncodedContent payload)
{
var cl = new HttpClient();
cl.Timeout = TimeSpan.FromSeconds(10);
HttpResponseMessage request = await cl.PostAsync((RESTURL + "/login"), payload);
request.EnsureSuccessStatusCode();
var response = await request.Content.ReadAsStringAsync();
LoginResponse res = JsonConvert.DeserializeObject<LoginResponse>(response);
return res;
}
Edit
I don't believe this is a duplicate of this as the issue is not about sending over https (which I believe it is actually already doing) but more about the TLS version it's using.

Digest Authentication Token Invalid after some time

i am just working on my first Windows Phone 8.1 app (Universal if this matters, but only Windows Phone implemented at the moment). And at first all is working very smooth but as soon as my app is running for about 25-30 Minutes I can no longer use my HttpClient. I use the Windows.Web.Http.HttpClient.
In my first trys I used a singleHttpClientand reused it all the time. As I became aware that this is not working I started using a newHttpClient` for each request. But still no luck.
This is my method to get a new HttpClient:
private HttpClient GetClient()
{
var filter = new HttpBaseProtocolFilter
{
AllowUI = false,
CacheControl = { WriteBehavior = HttpCacheWriteBehavior.NoCache },
ServerCredential =
new PasswordCredential(
BaseApiUri.ToString(),
credentials.UserName,
credentials.Password),
};
var httpClient = new HttpClient(filter);
var headers = httpClient.DefaultRequestHeaders;
var httpConnectionOptionHeaderValueCollection = headers.Connection;
httpConnectionOptionHeaderValueCollection.Clear();
headers.Accept.TryParseAdd("application/json");
headers.CacheControl.TryParseAdd("no-cache");
headers.Add("Pragma", "no-cache");
headers.Add("Keep-Alive", "false");
headers.Cookie.Clear();
return httpClient;
}
The extra code setting the headers and clearing cookies are my attempts to stop some kind of caching of connections under the surface that might happen. But still no luck.
My method to make requests my API is like the following:
private async Task<bool> PostNoResponseRequestTo(string relativeUri, object requestContent, CancellationToken cancellationToken)
{
var targetUri = new Uri(BaseApiUri, relativeUri);
var requestJson = JsonConvert.SerializeObject(requestContent);
var content = new HttpStringContent(requestJson, UnicodeEncoding.Utf8, "application/json");
try
{
using (var httpClient = this.GetClient())
{
var post =
await httpClient.PostAsync(targetUri, content).AsTask(cancellationToken).ContinueWith(
async request =>
{
using (var response = await request)
{
return response.IsSuccessStatusCode;
}
},
cancellationToken);
return await post;
}
}
catch (Exception)
{
return false;
}
}
This works fine for about 25-30 Minutes after which the calls to the api suddenly start to fail. I start getting a 401 but as you can see i have specified credentials and because those are working and do not change (hardcoded them to test this) i start believing that the problem is on the API side.
This is the response I get:
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 2, Content: Windows.Web.Http.HttpStreamContent, Headers:
{
Server: Microsoft-IIS/8.5
Date: Fri, 20 Mar 2015 14:25:06 GMT
WWW-Authenticate: Digest qop="auth",algorithm=MD5-sess,nonce="+Upgraded+NounceRemoved",charset=utf-8,realm="Digest", Negotiate, NTLM
X-Powered-By: ASP.NET
}
{
Content-Length: 1344
Content-Type: text/html
}
My API consists of a Asp.Net project with ServiceStack for its API functionality.
This is running on an IIS with activated digest authentication (all other are disabled).
By inspecting the logs i became aware of a failing API call in front of each successful call. But if i'm right this is by design of digest auth because i have not found a way to tell the client that the other side is using digest auth. I was able to specify this kind of information in my other .Net projects but for some reason Microsoft changed the code (and namespace) for the HttpClient. I am also aware of the HttpClient in the original namespace that you can get through nuget but this is not working for me as i get an error in my output window as soon as i make any call. This closes my app without any kind of information.
Back to the log i was able to get some information with the help of the extended logging and the tool to analyze them. The error is something like (can't access it right now will edit it later):'Invalid token passed to function/method'.
I really hope that someone can help me to solve this problem as it makes the app nearly unusable. My users have to restart the app every 15 Minutes to be on the save site.
Thanks for all advices that help me.
Try Checking the Machine Key setting in IIS. Automatically generate at runtime if tick will generate a new key every time the app pool is restarted. This might be causing your issue. The Machine Key can be set on the server, website or application level. As activated digest authentication is encrypted this might be the issue.
Managing Websites with IIS Manager (part 6) - The Machine Key and Windows Authentication

"Cannot redirect after HTTP headers have been sent." When returning HttpResponseMessage with HttpStatusCode.Unauthorized

I'm using the new Web Api beta and wish to return
HttpResponseMessage<MyObject>(new MyObject{ MyMessage = "Go Away!" }, HttpStatusCode.Unauthorized)
from one of my ApiController actions.
Forms Authentication hijacks the response, crashes and adds the error "Cannot redirect after HTTP headers have been sent." and it's html to the response.
Normal suppression techniques like this don't work with Web Api.
Has anyone found a work around to this?
I've looked at this forum post where people report the same problem but the solutions there don't work for this case. The first solution suggested uses the normal suppression technique which doesn't work for web api. The second uses a HttpMessageHandler to intercept the request before it gets to the controller, I want the controller to fire as normal.
After looking into the DelegatingHandler I can get access to the HttpResponseMessage but have no idea what to do with it to stop FormsAuth from redirecting.
I faced the same issue when using the Phil Haack's SuppressFormsAuthenticationRedirectModule
I managed to fix it in my case by clearing the server's error as shown below
private void OnEndRequest(object source, EventArgs args)
{
var context = (HttpApplication)source;
var response = context.Response;
if (context.Context.Items.Contains(SuppressAuthenticationKey))
{
context.Server.ClearError(); //Clearing server error
response.TrySkipIisCustomErrors = true;
response.ClearContent();
response.StatusCode = 401;
response.RedirectLocation = null;
}
}
Hi as this question still seems to be open I thought I would point out that the latest MVC 4 RC release now appears to have the Forms redirect disabled by default. I did some digging whilst replying to this question Prevent FormsAuthenticationModule of intercepting ASP.NET Web API responses

Categories

Resources