AsyncServerStreamingCall and failed authentication - c#

I have .Net 5 console client calling a service using gRPC and opening a bi-directional channel.
The code all works fine when I pass headers (the server is set up for Auth), but I am interested in seeing what happens when bad/no credentials are passed. I see on the server a 401 message as the call is not authenticated, but there is no indication of failure in the client, it just hangs.
The following works just fine, where response is AsyncServerStreamingCall<GetResponse>
response = client.GetSomeMethod(
new GetRequest
{
Parameter1 = args[0],
},
headers);
when I take the headers out, I still get back a response, but when I await the ResponseStream it just hangs.
var monitorTask = Task.Run(async () =>
{
await foreach (var result in response.ResponseStream.ReadAllAsync())
{
this.Results.Add(result);
In the working case, this simply blocks until the first result is streamed back by the server. In the not-working case, it just blocks.
How do I detect that the call to the server failed? Should I be seeing an exception or should I be checking a status field somewhere?

Related

Adding SSL cert causes 404 only in browser calls

I am working in an internal corporate environment. We have created a webapi installed on iis on port 85. We call this from another MVC HelperApp on port 86. It all works as expected. Now we want to tighten security and add an SSL cert to iis on port 444 and bind it to our API.
Initially we test it with Postman, SoapUI, and a C# console app and it all works. Now we try calling it from our MVC HelperApp and it returns a 404 sometimes.
Deeper debugging; I put the code into a C# DLL (see below). Using the console app I call the Dll.PostAPI and it works as expected. Now I call that same Dll.PostAPI from the MVC HelperApp and it won't work. When I step through the code I make it as far as this line await client.PostAsync(url, data); and the code bizarrely ends, it doesn't return and it doesn't throw an exception. Same for Post and Get. I figure it makes the call and nothing is returned, no response and no error.
Also, if I change the url to "https://httpbin.org/post" or to the open http port85 on iss it will work. I have concluded that the C# code is not the problem (but I'm open to being wrong).
Therefore I have come to the conclusion that for some reason the port or cert is refusing calls from browsers.
We are looking at:
the "Subject Alternative Name" but all the examples show
WWW.Addresses which we are not using.
the "Friendly Name" on the cert creation.
and CORS Cross-Origin Resource Sharing.
These are all subjects we lack knowledge in.
This is the calling code used exactly the same in the console app and the web app:
var lib = new HttpsLibrary.ApiCaller();
lib.makeHttpsCall();
This is what's in the DLL that gets called:
public async Task<string> makeHttpsCall()
{
try
{
List<Quote> quotes = new List<Quote>();
quotes.Add(CreateDummyQuote());
var json = JsonConvert.SerializeObject(quotes);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var url = "https://httpbin.org/post"; //this works in Browser
//url = "https://thepath:444//api/ProcessQuotes"; //444 DOES NOT WORK in browsers only. OK in console app.
//url = "http://thepath:85/api/ProcessQuotes"; //85 works.
var client = new HttpClient();
var response = await client.PostAsync(url, data); //<<<this line never returns when called from browser.
//var response = await client.GetAsync(url); //same outcome for Get or Post
var result = await response.Content.ReadAsStringAsync();
return result;
}
catch (Exception ex)
{
throw;
}
}

Why would my C# app fail on this REST request but but works fine through a browser?

I have a C# app and I am accessing some data over REST so I pass in a URL to get a JSON payload back. I access a few different URLs programmatically and they all work fine using this code below except one call.
Here is my code:
var url = "http://theRESTURL.com/rest/API/myRequest";
var results = GetHTTPClient().GetStringAsync(url).Result;
var restResponse = new RestSharp.RestResponse();
restResponse.Content = results;
var _deserializer = new JsonDeserializer();
where GetHTTPClient() is using this code below:
private HttpClient GetHTTPClient()
{
var httpClient = new HttpClient(new HttpClientHandler()
{
Credentials = new System.Net.NetworkCredential("usr", "pwd"),
UseDefaultCredentials = false,
UseProxy = true,
Proxy = new WebProxy(new Uri("http://myproxy.com:8080")),
AllowAutoRedirect = false
});
httpClient.Timeout = new TimeSpan(0,0, 3500);
return httpClient;
}
so as i said, the above code works fine but a bunch of different request but for one particular request, I am getting an exception inside of the
.GetStringAsync(url).Result
call with the error:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host
I get that error after waiting for about 10 minutes. What is interesting is that if I put that same URL that isn't working into Internet Explorer directly I do get the JSON payload back (after about 10 minutes as well). So i am confused at why
It would work fine directly from the browser but fail when using the code above.
It fails on this one request but other requests using the same code work fine programmatically.
Any suggestions for things to try or things I should ask the owner of the server to check out on their end to help diagnose what is going on?
I think the timeout is not an issue here, as the error states that connection has been closed remotely and the set timeout is about 58 minutes, which is more than enough compared to your other figures.
Have you tried looking at the requests itself? Might want to edit your question with those results.
If you remove line httpClient.Timeout = new TimeSpan(0,0, 3500); the issue should be solved but if the request would last 20 minutes you should wait all the time.

await HttpClient.SendAsync not throwing exception when expected

I have a Windows Phone 8 app containing code as follows:
using (var client = new HttpClient())
{
var httpRequest = new HttpRequestMessage(method, uri);
try
{
var response = client.SendAsync(httpRequest);
var httpResponse = await response;
if (httpResponse.IsSuccessStatusCode)
{
var result = await httpResponse.Content.ReadAsStringAsync();
return result;
}
else
{
HandleError(httpResponse);
return null;
}
}
catch (Exception ex)
{
throw;
}
}
If the client successfully connects to the server, I will get the expected results, including all the appropriate HTTP status codes and reason phrases.
If the client is unable to contact the server (e.g. incorrect domain/IP/port in the URL), the awaited task completes after some delay, with a 404 status and no reason phrase. The task never throws an exception. The task (the response variable in the code snippet) has the status of "ran to completion". Nothing about the result is indicative of the actual problem - be it networking failure, unreachable server, etc.
How can I capture more meaningful errors in the case where the URL points to a non-existent or unreachable server, socket connection refused, etc.? Shouldn't SendAsync be throwing specific exceptions for such cases?
FWIW, the client code is built into a PCL library using VS 2013 update 3 and running in the Windows Phone emulator, using System.Net.Http 2.2.28 from NuGet
Windows Phone's implementation of the .NET HttpClient is different from Desktop's implementation (wininet vs. custom stack). This is one of the incompatibilities that you need to be aware of, if there is a semantic difference for you.
In my simple test I do get a ReasonPhrase of "Not Found" on the phone emulator. Also you can see that the Headers collection is empty whereas if the server was found and actually returned a real 404 then there would be headers.

HttpClient GET request fails, POST Succeeds

In a Xamarin application (backed by ASP.NET WebApi), I'm having trouble getting [all of] my GET requests to succeed -- they return 404. In fact, when watching network traffic in Fiddler, I don't even see the request happen.
Here is [basically] what I'm doing:
public async Task<bool> ValidateSponsor(string attendeeId, string sponsorId)
{
string address = String.Format("{0}/Sponsors/?attendeeId={1}&sponsorId={2}", BASE_URI, attendeeId, sponsorId);
var response = await client.GetAsync(address);
var content = response.content;
if (!response.IsSuccessStatusCode)
throw new HttpRequestException("Check your network connection and try again.");
string result = await content.ReadAsStringAsync();
return Convert.ToBoolean(result);
}
If I copy out the address variable and paste it into a browser, it succeeds. POST requests (to different methods, of course) succeed. I've also tried using the PCL version RestSharp but get the same results -- POST succeeds and GET fails.
Edit:
This looks like it also may only be a problem when deployed to Azure, it works fine locally.

How to force IIS to send response headers without sending response body and closing connection

I am trying to stream dynamically generated data to a client over HTTP using IIS, and the connection has to remain open for a long period of time, and the server will send periodic status updates to the client while it is performing a time-consuming operation.
This MUST all be handled within ONE request, but I am using a WebClient.OpenRead() stream, which cannot be opened until the headers are sent.
How can I force IIS to send headers to the client, and later send a response body?
This behaviour is normally achievable by setting KeepAlive to true and setting Expect header to "100 and continue". By doing this, server will send the headers with result code 100.
I am not sure if this is possible using WebClient.
Use HttpWebRequest instead to be able to set the values above. In fact WebClient does nothing magical but using GET to get the data. Here is the code for calling OpenRead in Reflector:
try
{
request = this.m_WebRequest = this.GetWebRequest(this.GetUri(address));
Stream responseStream = (this.m_WebResponse = this.GetWebResponse(request)).GetResponseStream();
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "OpenRead", responseStream);
}
stream2 = responseStream;
}
catch (Exception exception)
{
//

Categories