Should WebClient be used in a using statement? - c#

If HttpClient is not supposed to be used in a using statement, see these links:
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/
So if your not supposed to use HttpClient in a using statement then why do so many examples out there put WebClient in a using statement (including Microsoft); also I have not yet seen an article about not putting WebClient in a using statement? Eventually at the lowest level both WebClient and HttpClient end up at the same place opening a TCP/IP socket. Is it what's in-between that makes WebClient acceptable to put in a using statement?
Note I have a reason for asking this question: I have a client application that runs on WinXP, Win7 full and embedded systems, the code that I use to POST XML to my backend host (CentOS system) looks like this:
void PostXml(string url, string xml, int id) {
try
{
//Console.WriteLine("POST Request: " + xml);
using (WebClient wc = new WebClient())
{
wc.Proxy = null; //DEBUG: testing this to see if it helps webclient post failure after time x
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
Byte[] d = Encoding.ASCII.GetBytes(xml);
//however Async below is better regardless for closing app and non interference with GUI
//Byte[] res = web.UploadData(url, "POST", d); //sychrounous will block until sent and response returned
wc.UploadDataCompleted += new UploadDataCompletedEventHandler(web_UploadDataCompleted);
wc.UploadDataAsync(new Uri(url), "POST", d, id);
}
}
catch (WebException ex)
{
string responseText = "";
using (var reader = new StreamReader(ex.Response.GetResponseStream()))
{
responseText = reader.ReadToEnd();
}
string logMsg = DateTime.Now.ToString("s") + " - PostXml WebClient webexception: " + ex.Message + "\r\n" +
" response: " + responseText + "\r\n\r\n";
File.AppendAllText(SPUClient.frmMain._logFile, logMsg);
}
catch (Exception ex) {
//Console.WriteLine("PostXml Exception: " + ex.Message);
string logMsg = DateTime.Now.ToString("s") + " - PostXml exception: " + ex.Message + "\r\n";
File.AppendAllText(SPUClient.frmMain._logFile, logMsg);
}
}
PostXml is called 2 times every 1 minute, I have 400 clients in the field that run this code above, some of them have run for more than a year with no errors. But we have had a few clients that run this code after running for several weeks, or several months just stop doing the UploadDataAsync( "POST" ) evidently? All we know at this time is we don't get an exception, the POST message does not leave the computer and on my CentOS log file I can see that it never arrived (the domain.net.access.log on CentOS shows all the POST connections from all my clients). Remember this rarely happens some clients have never failed, some run for months / weeks before this happens. Restarting the client application fixes the problem of course. Should I be using WebClient in a using statement could that be the cause of something like this issue or is it something else?

Related

Restsharp delay prior to call (15 sec) - postman instant

I have the following code in a C# WPF app. This has been working perfectly in testing for a month:
try
{
string zServerName = "http://" + dispenseDetails.dipenseServerCompName + ":8800/Api/";
var options = new RestClientOptions(zServerName);
var client = new RestClient(options);
var request = new RestRequest(endpoint + APIparameter);
request.Method = apiMethod;
Debug.WriteLine(zServerName + endpoint + APIparameter);
request.Method = apiMethod;
if (!getToken)
{
if (string.IsNullOrEmpty(dispenseDetails.curZToken))
{
dispenseDetails.curZToken = getNewToken();
Debug.WriteLine("Got new token: " + dispenseDetails.curZToken);
}
else
{
Debug.WriteLine("Already have token: " + dispenseDetails.curZToken);
}
request.AddHeader("Authorization", "Bearer " + dispenseDetails.curZToken);
}
var response = client.ExecuteAsync(request).Result;
Debug.WriteLine(response);
if (response.ErrorException != null)
{
msgBox.Show(null, "Connection failed. " + response.ResponseStatus);
return "false";
}
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var JsonString = response.Content;
Debug.WriteLine(JsonString);
return JsonString;
}
else
{
Utility.LogFile("API Fail", response.StatusCode.ToString() + ":" + response.Content, apiMethod + " " + endpoint, "zDispenseServer: " + APIparameter + reqBody, false);
return "false";
}
}
catch (Exception exe)
{
Utility.LogFile(exe.Message, "Critial Error: Cannot contact ZDispense Server", "Api Utility", "RestAPI",false);
return "false";
}
Now I am aware it isn't great code and I'm fixing up on the responses (I'm self taught amateur).
My issue is now when I make this call the comp hangs and waits and gets an answer... 15-> 30 secs later.
I understand I'm not using async/await and this will fix the hang, but it has always worked instantly.
TESTED:
I do exactly the same call (using same user and password and everything) with Postman
Status 200OK
Time 40ms
So postman is wokring as per usual.
Wireshark
I have never used wireshark but installed for this reason.
I tested with Postman and the instant I send the call it appears on Wireshark.
0.03s response time.
Tested with my app/restsharp:
0.03s response time BUT it takes about 15-30 secs to appear in wireshark.
My theory is that the call is fast (eg the call then response) as it shows on WS fast BUT it's like the call sits there and is delayed THEN makes the call...
I have other code and another API which is working perfectly fine using the exact code above but to a different server.
The "fast" server is my own nodejs API
This one is a companies API test software on a computer on my local network (home/personal).
I don't know if that matters but thought to mention it.
Could anyone point me in the right direction?
Am I right in saying if it doesnt appear in WS for 15 secs, that means its... "sitting" in Visual Studio before being sent, and if this is the case.... why??
I have no proxies, no weird interesting stuff.
Fresh install of Vis studio because I tried that in case I had some setting screwing things up.
EDIT:
It hangs at
var response = client.ExecuteAsync(request).Result;
Hang might not be the right word, I know it isnt an AWAIT but it used to pause for 0.5 sec but now it hangs for 15-30 secs
In WPF, you should either make your method async void and await ExecuteAsync or use the latest version with sync methods that were recently brought back. These methods do some advanced stuff with thread scheduling to ensure it doesn't block.

Win10 IOT / UWP: How to detect if a network device (Arduino) is availabe

I'd like to connect if my Arduino is available on the network. I'm trying to access the Arduino web server using an HTTP client and processing the JSON answer.
Since ping is not available in UWP what are my options? (see: Article)
One option would be to handle the exception of the HTTP client. But is there any more elegant way to check the connection before requesting the JSON data?
One method might be using the HTTPClient to do a GetAsync() and check the Status code coming out of it.
Depending on your time constraints, you can wait for it to time out naturally or pass a cancellation token to break it sooner than the defaults.
From here https://learn.microsoft.com/en-us/windows/uwp/networking/httpclient (slightly modified):
//Send the GET request asynchronously and retrieve the response as a string.
Windows.Web.Http.HttpResponseMessage httpResponse = new Windows.Web.Http.HttpResponseMessage();
string httpResponseBody = "";
try
{
//Send the GET request
httpResponse = await httpClient.GetAsync(requestUri);
if(httpResponse.IsSuccessStatusCode) { /* Do something with it */ }
else { /* Do fallback here */ }
}
catch (Exception ex)
{
httpResponseBody = "Error: " + ex.HResult.ToString("X") + " Message: " + ex.Message;
}

C# WebClient 404 Error Large String

This is wrecking my brain for a while now. The code works fine when I post a smaller XML string. As soon as I add more XML nodes and post, I get the infamous '404 Error'
I'm posting XML data as a string to a Generic Handler in C#.
string strXML = "Large XML Content Here";
WebClient client = new WebClient();
string xmlResult = "";
try
{
xmlResult = client.DownloadString(_workContext.AccountingWebServiceLink
+ "?action=updateprimary&xml="
+ System.Web.HttpUtility.UrlEncode(strXML));
}
catch(Exception e)
{
System.IO.File.AppendAllText(Server.MapPath("~/addressXMLReturnError.txt"),
"Error: " + e.Message + " returnValue = " + xmlResult);
}
I think it might have something to do with the server not accepting large strings?
Finally got it working using suggestions from comments above.
So posting the XML data is the best route for me.
Using code from this SO post > HTTP post XML data in C#
To receive the data on the other side, check out this link > https://code.msdn.microsoft.com/Enviar-datos-por-el-metodo-2e580ace

Windows Phone 8.1 Google Book REST Api call with HttpClient: HRESULT: 0x80072EFD

I am trying to write some app that needs to fetch info about books. That's why I am using Google Book Api. The Official library is not working on WP8.1 so I am trying to do everything by myself with the help of the Internet. That is what I wrote:
public async Task<RootObject> GetBooks(string query)
{
using (HttpClient httpClient = new HttpClient())
{
HttpResponseMessage response = new HttpResponseMessage();
string requestUri = googleApiUri + "q=" + query.Replace(" ", "+") + "&maxResults=10&orderBy=relevance&printType=books&projection=lite";
string jsonString = "";
try
{
jsonString = await httpClient.GetStringAsync(new Uri(requestUri));
}
catch (Exception ex)
{
string message = "Error = " + ex.HResult.ToString("X") +
" Message: " + ex.Message;
}
return ResponseToJson(jsonString);
}
}
private RootObject ResponseToJson(string message)
{
return JsonConvert.DeserializeObject<RootObject>(message);
}
However, the call httpClient.GetStringAsync is throwing me an error: "Exception from HRESULT: 0x80072EFD". I've no idea why's that happening and I can't find anything on the Internet about such exception. Am I doing something wrong with httpClient? I will be very greatful for any help!
Thank You in advance!
BestRegards,
Roman
Do you have suffisent authorization for your app ? Usually, there is a file called WMAppManifest.xml in the Properties of your project. Open it and go to the "Capabilities" tab. Make sure ID_CAP_NETWORKING is checked. This will give your app the authorization to access the Internet.

How to display optional fields in response when using C# WebClient and getting exceptions?

I'm using WebClient to do a POST to a server like so:
string URI = "http://mydomain.com/foo";
string myParameters =
"&token=1234" +
"&text=" + HttpUtility.UrlEncode(someVariable);
using (WebClient wc = new WebClient())
{
try
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
string HtmlResult = wc.UploadString(URI, myParameters);
}
catch (WebException e)
{
return e.Message;
}
}
I sometimes can get exceptions thrown due to HTTP 403 (forbidden). In those cases, I want to know the exact reason. Digging into the service I'm calling into, it is documneted that it will optionally return an errorDetail field like so:
"code": 403,
"errorType": "not_authorized",
"errorDetail": "Can reply on a checkin at most once."
However, when I'm stepping through the code in Visual Studio, I don't see how I can get the errorDetail field. It doesn't apepar to be part of the WebException.
Is there a way to get it so I could display is something like:
return e.Message + " -- " + e.errorDetail
?
errorDetail is not part of the HTTP specification so WebClient does not know about it. For the same reason you will not find it anywhere in the BCL.
What you probably want is the response body so you can parse it (maybe as JSON? Your data looks like it).
You can get the response object from WebException.Response. Read it just like you normally would read a response.
Be aware that this property might be null if there is no response (due to network error, for example).

Categories

Resources