Error checking when using HttpClient for asynchronous file downloads - c#

This question is a followup to Threading issues when using HttpClient for asynchronous file downloads.
To get a file transfer to complete asynchronously using HttpClient, you need to add HttpCompletionOption.ResponseHeadersRead to the SendAsync request. Thus, when that call completes, you will be able to determine that all was well with the request and the response headers by adding a call to EnsureSuccessStatusCode. However the data is possibly still being transferred at this point.
How can you detect errors which happen after the headers are returned but before the data transfer is complete? How would said errors manifest themselves?
Some example code follows, with the point of the question marked at line 109)with the comment: "// *****WANT TO DO MORE ERROR CHECKING HERE**"
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace TestHttpClient2
{
class Program
{
/* Use Yahoo portal to access quotes for stocks - perform asynchronous operations. */
static string baseUrl = "http://real-chart.finance.yahoo.com/";
static string requestUrlFormat = "/table.csv?s={0}&d=0&e=1&f=2016&g=d&a=0&b=1&c=1901&ignore=.csv";
static void Main(string[] args)
{
var activeTaskList = new List<Task>();
string outputDirectory = "StockQuotes";
if (!Directory.Exists(outputDirectory))
{
Directory.CreateDirectory(outputDirectory);
}
while (true)
{
Console.WriteLine("Enter symbol or [ENTER] to exit:");
string symbol = Console.ReadLine();
if (string.IsNullOrEmpty(symbol))
{
break;
}
Task downloadTask = DownloadDataForStockAsync(outputDirectory, symbol);
if (TaskIsActive(downloadTask))
{
// This is an asynchronous world - lock the list before updating it!
lock (activeTaskList)
{
activeTaskList.Add(downloadTask);
}
}
else
{
Console.WriteLine("task completed already?!??!?");
}
CleanupTasks(activeTaskList);
}
Console.WriteLine("Cleaning up");
while (CleanupTasks(activeTaskList))
{
Task.Delay(1).Wait();
}
}
private static bool CleanupTasks(List<Task> activeTaskList)
{
// reverse loop to allow list item deletions
// This is an asynchronous world - lock the list before updating it!
lock (activeTaskList)
{
for (int i = activeTaskList.Count - 1; i >= 0; i--)
{
if (!TaskIsActive(activeTaskList[i]))
{
activeTaskList.RemoveAt(i);
}
}
return activeTaskList.Count > 0;
}
}
private static bool TaskIsActive(Task task)
{
return task != null
&& task.Status != TaskStatus.Canceled
&& task.Status != TaskStatus.Faulted
&& task.Status != TaskStatus.RanToCompletion;
}
static async Task DownloadDataForStockAsync(string outputDirectory, string symbol)
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUrl);
client.Timeout = TimeSpan.FromMinutes(5);
string requestUrl = string.Format(requestUrlFormat, symbol);
var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
var response = await client.SendAsync(request,
HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
using (var httpStream = await response.Content.ReadAsStreamAsync())
{
var timestampedName = FormatTimestampedString(symbol, true);
var filePath = Path.Combine(outputDirectory, timestampedName + ".csv");
using (var fileStream = File.Create(filePath))
{
await httpStream.CopyToAsync(fileStream);
}
}
// *****WANT TO DO MORE ERROR CHECKING HERE*****
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("Exception on thread: {0}: {1}\r\n",
System.Threading.Thread.CurrentThread.ManagedThreadId,
ex.Message,
ex.StackTrace);
}
catch (Exception ex)
{
Console.WriteLine("Exception on thread: {0}: {1}\r\n",
System.Threading.Thread.CurrentThread.ManagedThreadId,
ex.Message,
ex.StackTrace);
}
}
static volatile string lastTimestampedString = string.Empty;
static volatile string dummy = string.Empty;
static string FormatTimestampedString(string message, bool uniquify = false)
{
// This is an asynchronous world - lock the shared resource before using it!
lock (dummy)
//lock (lastTimestampedString)
{
Console.WriteLine("IN - Thread: {0:D2} lastTimestampedString: {1}",
System.Threading.Thread.CurrentThread.ManagedThreadId,
lastTimestampedString);
string newTimestampedString;
while (true)
{
DateTime lastDateTime = DateTime.Now;
newTimestampedString = string.Format(
"{1:D4}_{2:D2}_{3:D2}_{4:D2}_{5:D2}_{6:D2}_{7:D3}_{0}",
message,
lastDateTime.Year, lastDateTime.Month, lastDateTime.Day,
lastDateTime.Hour, lastDateTime.Minute, lastDateTime.Second,
lastDateTime.Millisecond
);
if (!uniquify)
{
break;
}
if (newTimestampedString != lastTimestampedString)
{
break;
}
//Task.Delay(1).Wait();
};
lastTimestampedString = newTimestampedString;
Console.WriteLine("OUT - Thread: {0:D2} lastTimestampedString: {1}",
System.Threading.Thread.CurrentThread.ManagedThreadId,
lastTimestampedString);
return lastTimestampedString;
}
}
}
}

I have copied and slightly cleaned up the relevant code.
var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
var response = await client.SendAsync(request,
HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
using (var httpStream = await response.Content.ReadAsStreamAsync())
{
var timestampedName = FormatTimestampedString(symbol, true);
var filePath = Path.Combine(outputDirectory, timestampedName + ".csv");
using (var fileStream = File.Create(filePath))
{
await httpStream.CopyToAsync(fileStream);
}
}
The question is, what if something goes wrong during reading the stream and copying it into your file?
All logical errors have already been addressed as part of the HTTP request and response cycle: the server has received your request, it has decided it is valid, it has responded with success (header portion of response), and it is now sending you the result (body portion of response).
The only errors that could occur now are things like the server crashing, the connection being lost, etc. My understanding is that these will manifest as HttpRequestException, meaning you can write code like this:
try
{
using (var httpStream = await response.Content.ReadAsStreamAsync())
{
var timestampedName = FormatTimestampedString(symbol, true);
var filePath = Path.Combine(outputDirectory, timestampedName + ".csv");
using (var fileStream = File.Create(filePath))
{
await httpStream.CopyToAsync(fileStream);
}
}
}
catch (HttpRequestException e)
{
...
}
The documenation doesn't say much, unfortunately. The reference source doesn't either. So your best bet is to start with this and maybe log all exceptions that are not HttpRequestException in case there is another exception type that could be thrown during the download of the response body.

If you want to narrow it down to the part which is between the header read and the content read, you actually leave yourself with the asynchronous buffer read:
var httpStream = await response.Content.ReadAsStreamAsync();
If you look whats going on inside the method, you'll see:
public Task<Stream> ReadAsStreamAsync()
{
this.CheckDisposed();
TaskCompletionSource<Stream> tcs = new TaskCompletionSource<Stream>();
if (this.contentReadStream == null && this.IsBuffered)
{
this.contentReadStream = new MemoryStream(this.bufferedContent.GetBuffer(),
0, (int)this.bufferedContent.Length,
false, false);
}
if (this.contentReadStream != null)
{
tcs.TrySetResult(this.contentReadStream);
return tcs.Task;
}
this.CreateContentReadStreamAsync().ContinueWithStandard(delegate(Task<Stream> task)
{
if (!HttpUtilities.HandleFaultsAndCancelation<Stream>(task, tcs))
{
this.contentReadStream = task.Result;
tcs.TrySetResult(this.contentReadStream);
}
});
return tcs.Task;
}
CreateContentReadStreamAsync is the one doing all the reading, internally, it will call LoadIntoBufferAsync, which you can find here.
Basically, you can see the it encapsulates IOException and ObjectDisposedException, or an ArgumentOutOfRangeException is the buffer is larger than 2GB (although i think that will be highly rare).

Related

Parallel HTTP requests using System.Net.Http.HttpClient

I'm trying to figure out the correct way to parallelize HTTP requests using Task and async/await. I'm using the HttpClient class which already has async methods for retrieving data. If I just call it in a foreach loop and await the response, only one request gets sent at a time (which makes sense because during the await, control is returning to our event loop, not to the next iteration of the foreach loop).
My wrapper around HttpClient looks as such
public sealed class RestClient
{
private readonly HttpClient client;
public RestClient(string baseUrl)
{
var baseUri = new Uri(baseUrl);
client = new HttpClient
{
BaseAddress = baseUri
};
}
public async Task<Stream> GetResponseStreamAsync(string uri)
{
var resp = await GetResponseAsync(uri);
return await resp.Content.ReadAsStreamAsync();
}
public async Task<HttpResponseMessage> GetResponseAsync(string uri)
{
var resp = await client.GetAsync(uri);
if (!resp.IsSuccessStatusCode)
{
// ...
}
return resp;
}
public async Task<T> GetResponseObjectAsync<T>(string uri)
{
using (var responseStream = await GetResponseStreamAsync(uri))
using (var sr = new StreamReader(responseStream))
using (var jr = new JsonTextReader(sr))
{
var serializer = new JsonSerializer {NullValueHandling = NullValueHandling.Ignore};
return serializer.Deserialize<T>(jr);
}
}
public async Task<string> GetResponseString(string uri)
{
using (var resp = await GetResponseStreamAsync(uri))
using (var sr = new StreamReader(resp))
{
return sr.ReadToEnd();
}
}
}
And the code invoked by our event loop is
public async void DoWork(Action<bool> onComplete)
{
try
{
var restClient = new RestClient("https://example.com");
var ids = await restClient.GetResponseObjectAsync<IdListResponse>("/ids").Ids;
Log.Info("Downloading {0:D} items", ids.Count);
using (var fs = new FileStream(#"C:\test.json", FileMode.Create, FileAccess.Write, FileShare.Read))
using (var sw = new StreamWriter(fs))
{
sw.Write("[");
var first = true;
var numCompleted = 0;
foreach (var id in ids)
{
Log.Info("Downloading item {0:D}, completed {1:D}", id, numCompleted);
numCompleted += 1;
try
{
var str = await restClient.GetResponseString($"/info/{id}");
if (!first)
{
sw.Write(",");
}
sw.Write(str);
first = false;
}
catch (HttpException e)
{
if (e.StatusCode == HttpStatusCode.Forbidden)
{
Log.Warn(e.ResponseMessage);
}
else
{
throw;
}
}
}
sw.Write("]");
}
onComplete(true);
}
catch (Exception e)
{
Log.Error(e);
onComplete(false);
}
}
I've tried a handful of different approaches involving Parallel.ForEach, Linq.AsParallel, and wrapping the entire contents of the loop in a Task.
The basic idea is to keep of track of all the asynchronous tasks, and awaiting them at once. The simplest way to do this is to extract the body of your foreach to a separate asynchronous method, and do something like this:
var tasks = ids.Select(i => DoWorkAsync(i));
await Task.WhenAll(tasks);
This way, the individual tasks are issued separately (still in sequence, but without waiting for the I/O to complete), and you await them all at the same time.
Do note that you will also need to do some configuration - HTTP is throttled by default to only allow two simultaneous connections to the same server.

HttpClient.GetAsync(...) "deadlock" when there is no internet connection

Recenly I found some sort of bug while using System.Net.http.HttpClient().GetAsync(...)
When in the middle process of GetAsync(..), if I disconnect my internet connection, the app just act like deadlock, and no exception catch, even I wait for few minutes.
Here is the example of code:
private async Task<WriteableBitmap> loadImageAsync(string url)
{
using (var httpClient = new HttpClient())
{
//When this line of code start execute, immediately disable the internet connection
var response = await httpClient.GetAsync(url);
//Once it get stuck at GetAsync(..), it won't execute the codes below
byte[] imageByte = await response.Content.ReadAsByteArrayAsync();
WriteableBitmap bitmap = new WriteableBitmap(1920, 1080);
using (InMemoryRandomAccessStream randomStream = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(randomStream))
{
writer.WriteBytes(imageByte);
await writer.StoreAsync();
await writer.FlushAsync();
writer.DetachStream();
}
randomStream.Seek(0);
await bitmap.SetSourceAsync(randomStream);
}
return bitmap;
}
}
I had try to set timeout to the httpClient, but it won't care what I set if there is no internet connection.
Is there any way to catch if the internet connection is disconnected, or did I miss something?
Edit: another async task that await loadImageAsync(..)
public async Task GetImagesAsync()
{
//skip if image is currently loading
if (IsImageLoading) { return; }
IsImageLoading = true;
ImageObjs.Clear();
try
{
int numberOfLoad = (int)((double)_LocalSettings.Values[NUMBER_OF_IMAGE_LOAD_SETTINGS]);
string region = _LocalSettings.Values[REGION].ToString();
#region Get Bing Image info
string jsonString = await new HttpClient().GetStringAsync($"http://www.bing.com/HPImageArchive.aspx?format=js&n={numberOfLoad}&mkt={region}");
ImageCollection imageCollection = JsonConvert.DeserializeObject<ImageCollection>(jsonString);
#endregion
#region Download images
foreach (var i in imageCollection.images)
{
string url;
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
url = i.url.Replace("1920x1080", "1080x1920");
}
else
{
url = i.url;
}
ImageObjs.Add(new ImageObj(await loadImageAsync(bingLink + url), i.copyright, url, i.copyrightlink, region));
}
showToastNotification(_MainViewModel.ImageObjs.Count.ToString() + " images loaded.");
#endregion
}
catch
{
//if connection failed
}
finally
{
IsImageLoading = false;
}
}
have you tried setting timeout with CancelationToken?
var tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(TimeSpan.FromSeconds(15));
try
{
var response = await httpClient.GetAsync(url, tokenSource.Token);
}
catch (TaskCanceledException ex)
{
// handle timeout here
}

saveStringToLocalFile in WindowsPhone 8.1 in Universal 8.1 App C#

I have this Function:
public async static Task<JsonObject> GetObject(string api)
{
try
{
JsonObject jsonObject = new JsonObject();
if (!IsInternetConnected())
{
string x = await DataBase.readStringFromLocalFile(api + ".txt");
jsonObject = JsonObject.Parse(x);
}
else
{
string x = "";
XDocument doc = XDocument.Load("DataLibrary/apis.xml");
var items = doc.Descendants("string");
foreach (XElement item in items)
{
if (item.Attribute("name").Value == api)
{
HttpClient webclient = new HttpClient();
HttpResponseMessage resp = webclient.PostAsync(new Uri(item.Value.ToString()), null).Result; //here
x = await resp.Content.ReadAsStringAsync();
try
{
await DataBase.saveStringToLocalFile(api + ".txt", x);
Debug.WriteLine("after writing");
}
catch (Exception ex)
{
throw ex;
}
Debug.WriteLine("after after writing");
jsonObject = JsonObject.Parse(x);
break;
}
}
}
return jsonObject;
}
catch (Exception)
{
MainPage.ShowCustomMessage(request_error_allert);
return new JsonObject();
}
}
And this is the saveStringToFile Function that I took from this article: https://pumpkinszwan.wordpress.com/2014/10/27/read-and-write-text-files-windows-8-1-phone-8-1-universal-apps/
public static async Task saveStringToLocalFile(string filename, string content)
{
// saves the string 'content' to a file 'filename' in the app's local storage folder
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(content.ToCharArray());
Debug.WriteLine("1");
// create a file with the given filename in the local folder; replace any existing file with the same name
StorageFile newFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
Debug.WriteLine("2");
// write the char array created from the content string into the file
using (var stream = await newFile.OpenStreamForWriteAsync())
{
await stream.WriteAsync(fileBytes, 0, fileBytes.Length);
Debug.WriteLine("3");
}
Debug.WriteLine("4");
}
I am calling GetObject 2 times with 2 different APIs.
When the code reaches the saveStringToFile Function, it crashes:
sometimes it crashes inside the saveStringTofile after
Debug.WriteLine("1");
sometimes after Debug.WriteLine("2");
sometimes after Debug.WriteLine("3");
sometimes after Debug.WriteLine("after writing");
sometimes it works the first time with the first API and crashes
with the second.
Its behaviour is really weird, I am trying to catch it with every breakpoint but it crashes randomly every single time. Anything I am missing?

async task cancellation c# xamarin

I have a functionality of search users. I have provided a textview and on that textview changed method I'm firing a method to get data from web server. But I'm facing problem when user types letter, because all the api hits done in async task. Service should be hit after 100 milli-sec of wait, means if user types a letter "a" then doesn't type for 100 milli-sec then We have to hit the service. But if user types "a" then "b" then "c", so one service should be hit for "abc", not for all.
I followed the official link, but it doesn't help me
https://msdn.microsoft.com/en-us/library/jj155759.aspx
So basically here is my code
textview.TextChange+= (sender,e) =>{
CancellationTokenSource cts = new CancellationTokenSource();
await Task.Delay(500);
// here some where I have to pass cancel token
var lst = await APIClient.Instance.GetUserSearch("/user/get?searchTerm=" + newText, "application/json",cts);
if (lst != null && lst.Count > 0){
lstSearch.AddRange(lst);
}
}
Here is my method to GetUser
public async Task<JResponse> GetUserSearch<JResponse>(string uri, string contentType,CancellationToken cts)
{
try
{
Console.Error.WriteLine("{0}", RestServiceBaseAddress + uri);
string url = string.Format("{0}{1}", RestServiceBaseAddress, uri);
var request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = contentType;
if (Utility.CurrentUser != null && !string.IsNullOrWhiteSpace(Utility.CurrentUser.AuthToken))
{
request.Headers.Add("api_key", Utility.CurrentUser.AuthToken);
}
request.Method = "POST";
var payload = body.ToString();
request.ContentLength = payload.Length;
byte[] byteArray = Encoding.UTF8.GetBytes(body.ToString());
request.ContentLength = byteArray.Length;
using (var stream = await request.GetRequestStreamAsync())
{
stream.Write(byteArray, 0, byteArray.Length);
stream.Close();
}
using (var webResponse = await request.GetResponseAsync())
{
var response = (HttpWebResponse)webResponse;
using (var reader1 = new StreamReader(response.GetResponseStream()))
{
Console.WriteLine("Finished : {0}", uri);
var responseStr = reader1.ReadToEnd();
var responseObj = JsonConvert.DeserializeObject<JResponse>(
responseStr,
new JsonSerializerSettings()
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
return responseObj;
}
}
}
catch (System.Exception ex)
{
Utility.ExceptionHandler("APIClient", "ProcessRequestAsync", ex);
}
return default(JResponse);
}
In your example, you are creating a CancellationTokenSource - you need to hold a reference to it, so that the next time the handler is invoked, the previous search can be cancelled. Here is an example console app that you should be able to run, but the important piece is in the handler.
private CancellationTokenSource _cts;
private async void TextChangedHandler(string text) // async void only for event handlers
{
try
{
_cts?.Cancel(); // cancel previous search
}
catch (ObjectDisposedException) // in case previous search completed
{
}
using (_cts = new CancellationTokenSource())
{
try
{
await Task.Delay(TimeSpan.FromSeconds(1), _cts.Token); // buffer
var users = await _userService.SearchUsersAsync(text, _cts.Token);
Console.WriteLine($"Got users with IDs: {string.Join(", ", users)}");
}
catch (TaskCanceledException) // if the operation is cancelled, do nothing
{
}
}
}
Be sure to pass the CancellationToken into all of the async methods, including those that perform the web request, this way you signal the cancellation right down to the lowest level.
Try to use timer. First time then you change text - you create it. Then you change text after that - you restart timer. If you don't change text for 700 milliseconds - timer will fire PerformeSearch method. Use Timeout.Infinite for timer period parameter to prevent it from restarting.
textview.TextChange += (sender,e) =>
{
if (_fieldChangeTimer == null)
_fieldChangeTimer = new Timer(delegate
{
PerformeSearch();
}, null, 700, Timeout.Infinite);
else
{
_fieldChangeTimer.Change(700, Timeout.Infinite);
}
};
Instantiate the CancellationTokenSource.
cts = new CancellationTokenSource(); Example method
private void cancelButton_Click(object sender, RoutedEventArgs e)
{
if (cts != null)
{
cts.Cancel();
}
}

Can't get Task.Result to return string unless I add a Thread.Sleep

First time asking a question here I'll try to be as specific as possible.
I am working with a WebBased Api at work and I am having a difficult time getting the Task to return a result.
I have a trade class as such with a Buy method and a GetOrderNumber method. On my MainForm I am using a Task to execute the Trade and then retrieve the ordernumber associated with that trade.
NewTrade Test = new NewTrade();
Task<string> tmp = Task.Factory.StartNew(() => Test.Buy("JPM.NY", 100, 59.50));
string reqid = tmp.Result;
Task<string> tmp2 = Task.Factory.StartNew(() => Test.GetOrderNumber(reqid));
Console.WriteLine(tmp2.Result);
The First Task returns a REQID number. The second Task uses the REQID number and returns the actual ORDER NUMBER for the Trade Placed.
The problem I'm running into is I get the ReqID number from the first task but I return blank on the second task.
IF HOWEVER I add a Thread.sleep() between the first and second task I get the ordernumbers.
I'm using Tasks becasue eventually there will be hundreds of orders being placed it's critical to have the ordernumber for every order.
class NewTrade
{
public string Buy(string stkName, int stkShares, double limitPrice)
{
try
{
using (MyWebClient client = new MyWebClient())
{
Stream data = client.OpenRead("http://localhost:8080/ExecuteOrder?symbol=" + stkName + "&limitprice=" + limitPrice + "&ordername=ARCA%20Buy%20ARCX%20Limit%20DAY&shares=" + stkShares);
StreamReader reader = new StreamReader(data);
string s = reader.ReadToEnd();
s = getBetween(s, "<Content>", "</Content>"); //this is a util function to parse the result
// MessageBox.Show(s.ToString());
data.Close();
reader.Close();
return s;
}
}
catch (WebException e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return "Nothing";
}
}
public string GetOrderNumber(string id)
{
string s = "";
using (MyWebClient client = new MyWebClient())
{
try
{
WebRequest request = WebRequest.Create("http://localhost:8080/GetOrderNumber?requestid=" + id);
WebResponse response = request.GetResponse();
var reader = new StreamReader(response.GetResponseStream());
s = reader.ReadToEnd();
Console.WriteLine(s);
return s;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return "";
}
}
}
}
Using Tasks can make your application more scalable as you are enabling threads to handle other tasks while the asynchronous task is in progress. That being said, using Task.Run or Task.Factory.StartNew to do IO tasks in the background defeats that purpose. You need to make your methods truly async by calling the async API of the IO constructs you are using. Try changing your code to something like this:
public Task<string> MakeTradeAsync()
{
NewTrade Test = new NewTrade();
string reqid = await Test.Buy("JPM.NY", 100, 59.50);
string orderNumber = await Test.GetOrderNumber(reqid);
Console.WriteLine(orderNumber);
return orderNumber;
}
That will require you to make Test.Buy and Test.GetOrderNumber async as well. Which you can do by using async APIs to access your server data.
public async Task<string> Buy(string stkName, int stkShares, double limitPrice)
{
try
{
using (MyWebClient client = new MyWebClient())
{
// use async API here to get the data, assuming existance of OpenReadAsync
Stream data = await client.OpenReadAsync("http://localhost:8080/ExecuteOrder?symbol=" + stkName + "&limitprice=" + limitPrice + "&ordername=ARCA%20Buy%20ARCX%20Limit%20DAY&shares=" + stkShares);
StreamReader reader = new StreamReader(data);
string s = reader.ReadToEnd();
s = getBetween(s, "<Content>", "</Content>"); //this is a util function to parse the result
// MessageBox.Show(s.ToString());
data.Close();
reader.Close();
return s;
}
}
catch (WebException e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return "Nothing";
}
}
public async Task<string> GetOrderNumber(string id)
{
string s = "";
using (MyWebClient client = new MyWebClient())
{
try
{
WebRequest request = WebRequest.Create("http://localhost:8080/GetOrderNumber?requestid=" + id);
WebResponse response = await request.GetResponseAsync();
var reader = new StreamReader(response.GetResponseStream());
s = await reader.ReadToEndAsync();
Console.WriteLine(s);
return s;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return "";
}
}
}

Categories

Resources