Incorporating GZIP into Web API - c#

I have a C# application that communicates to my Web API service fine when there is no GZIP being used. When I apply GZIP, my [FromBody] variable is null and I can't seem to pinpoint why this is happening.
If I put a breakpoint in the web api, I can see that data is null when GZIP is applied. When it's not, it is populated.
Any input would be greatly appreciated. If you need any other code examples please let me know
Update Routing Class
public class UpdateRouting
{
public UpdateRouting()
{
Routes = new List<Routing>();
}
public List<Routing> Routes { get; set; }
}
Collect data
private void btnTestRoutingSend_Click(object sender, EventArgs e)
{
try
{
var response = new ResponseObj();
using (var mainContext = new EntityModel())
{
var nodes = mainContext.Nodes.Where(x => x.SystemType == "Dev").ToList();
var updRouting = new UpdateRouting();
foreach (var n in nodes)
{
using (var nodeContext = new EntityModel(connString))
{
var accounts = nodeContext.Accounts;
foreach (var acct in accounts)
{
//code to map accounts to route
}
var customers = nodeContext.Customers;
foreach (var cust in customers)
{
//code to map customer to route
}
}
}
response = webcontext.SendPost<ResponseObj>(updRouting, "Routing", "SyncRouting");
}
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
SendPost Method
public T SendPost<T>(object update, string controller, string action)
{
var url = _baseURL + String.Format("api/{0}/{1}", controller, action), update);
T retval = default(T);
var uri = new Uri(_baseUri, url);
try
{
var request = GetRequest(uri, method);
if (content != null)
{
var json = GetBodyString(content);
if (!_useCompression)
{
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
var json = GetBodyString(content);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
} else{
using (var gzipStream = new GZipStream(request.GetRequestStream(), CompressionMode.Compress, false))
{
using (var streamWriter = new StreamWriter(gzipStream))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
}
httpWebRequest.Headers.Add("Content-Encoding", "gzip");
}
}
var response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
retval = GetObject<T>(result);
}
}
catch (Exception e)
{
_log.Error(string.Format("Error sending {0} request to {1}", method, uri.ToString()), e);
}
return retval;
}
Get Request
protected virtual HttpWebRequest GetRequest(Uri uri, string method)
{
var retval = (HttpWebRequest)WebRequest.Create(uri);
retval.Timeout = 1000 * 60 * 5;
retval.Accept = "application/json";
retval.KeepAlive = true;
retval.ContentType = "application/json";
retval.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
retval.Method = method;
return retval;
}
API Call
[System.Web.Http.HttpPost]
[Route("SyncRouting")]
public ResponseObj SyncRouting([FromBody] UpdateRouting data)
{
var response = new ResponseObj();
try
{
// do stuff
response.Successful = true;
return response;
}
catch (Exception e)
{
response.Successful = false;
response.Errors.Add(new ErrorMsg
{
Message = "Error - " + e.ToString(),
ExceptionMessage = e.Message,
StackTrace = e.StackTrace,
InnerException = e.InnerException.ToString()
});
return response;
}
}

Related

Sending Multiple Files in a single Request to API

I am fairly new to API's. I am writing a "simple" API that will convert .docx files to .pdf files and return the pdf's back to the client for saving. I have the code working for a single file but I wanted to code the API to handle multiple files in a single request. Now the API is not receiving the request. I can provide the working code with a single file if requested.
I am sure I am missing something simple. Please see below and see if anyone see's something that I could be doing better or why the API is not receiving the POST request.
Client:
List<string> documents = new List<string>();
private async void btnConvert_Click(object sender, EventArgs e)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(BaseApiUrl);
//client.DefaultRequestHeaders.Add("Accept", "application/json");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);
foreach (string s in docPaths)
{
byte[] bte;
bte = File.ReadAllBytes(docPath);
string data = JsonConvert.SerializeObject(Convert.ToBase64String(bte));
documents.Add(data);
}
using (var formData = new MultipartFormDataContent())
{
foreach (string s in documents)
{
//add content to form data
formData.Add(new StringContent(s, Encoding.UTF8, "application/json"));
}
// List of Http Reponse Messages
var conversions = documents.Select(doc => client.PostAsync(BaseApiUrl + ApiUrl, formData)).ToList();
//Wait for all the requests to finish
await Task.WhenAll(conversions);
//Get the responses
var responses = conversions.Select
(
task => task.Result
);
foreach (var r in responses)
{
// Extract the message body
var s = await r.Content.ReadAsStringAsync();
SimpleResponse res = JsonConvert.DeserializeObject<SimpleResponse>(s);
if (res.Success)
{
byte[] pdf = Convert.FromBase64String(res.Result.ToString());
// Save the PDF here
}
else
{
// Log issue
}
}
}
}
API: This is not getting the request so this function is not complete. I need to figure out why it not being hit.
[HttpPost]
public async Task<List<SimpleResponse>> Post([FromBody]string request)
{
var response = new List<SimpleResponse>();
Converter convert = new Converter();
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var requestContents in provider.Contents)
{
try
{
//var result = convert.CovertDocToPDF(requestContents, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);
//response.Add(new SimpleResponse() { Result = result, Success = true });
}
catch (Exception ex)
{
response.Add(new SimpleResponse() { Success = false, Exception = ex, Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") } });
}
}
return response;
}
SimpleResponse Model:
public class SimpleResponse
{
public object Result { get; set; }
public bool Success { get; set; }
public Exception Exception { get; set; }
public List<string> Errors { get; set; }
}
UPDATE
Did suggestions made by #jdweng and I am getting a null response on the API POST
Client:
public async void btnConvert_Click(object sender, EventArgs e)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(BaseApiUrl);
client.DefaultRequestHeaders.Add("Accept", "application/json");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//application/json
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);
List<string> requests = new List<string>();
byte[] bte;
// New Code per the suggestion
foreach (string s in docPaths)
{
bte = File.ReadAllBytes(s);
requests.Add(Convert.ToBase64String(bte));
}
// End new code
string data = JsonConvert.SerializeObject(requests);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
HttpResponseMessage response1 = client.PostAsync(BaseApiUrl + ApiUrl, request.Content).Result;
Task<string> json = response1.Content.ReadAsStringAsync();
SimpleResponse response = JsonConvert.DeserializeObject<SimpleResponse>(json.Result);
//result = JsonConvert.DeserializeObject(result).ToString();
if (response.Success)
{
bte = Convert.FromBase64String(response.Result.ToString());
if (File.Exists(tempPdfPath))
{
File.Delete(tempPdfPath);
}
System.IO.File.WriteAllBytes(tempPdfPath, bte);
}
else
{
}
}
}
Server:
[HttpPost]
public async Task<List<SimpleResponse>> Post([FromBody]string request)
{
// The request in NULL....
List<SimpleResponse> responses = new List<SimpleResponse>();
List<string> resp = JsonConvert.DeserializeObject(request) as List<string>;
try
{
Converter convert = new Converter();
foreach (string s in resp)
{
var result = convert.CovertDocToPDF(request, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);
responses.Add(new SimpleResponse()
{
Result = result,
Success = true
});
}
}
catch (Exception ex)
{
responses.Add(new SimpleResponse()
{
Result = null,
Success = true,
Exception = ex,
Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") }
});
}
return responses;
}
I have finally solved the issues and can now successfully send multiple .docx files to the API and get the .pdf files back from the API. Now I want to figure out how to send each files on it's own thread instead of all together.
Client:
public async void btnConvert_Click(object sender, EventArgs e)
{
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(BaseApiUrl);
client.DefaultRequestHeaders.Add("Accept", "application/json");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);
List<string> requests = new List<string>();
byte[] bte;
foreach (string s in docPaths)
{
bte = File.ReadAllBytes(s);
requests.Add(Convert.ToBase64String(bte));
}
var data = JsonConvert.SerializeObject(requests);
request.Content = new StringContent(data, Encoding.UTF8, "application/json");
HttpResponseMessage response1 = await client.PostAsync(BaseApiUrl + ApiUrl, request.Content);
Task<string> json = response1.Content.ReadAsStringAsync();
var response = JsonConvert.DeserializeObject<List<SimpleResponse>>(json.Result);
foreach (SimpleResponse sr in response)
{
if (sr.Success)
{
bte = Convert.FromBase64String(sr.Result.ToString());
string rs = RandomString(16, true);
string pdfFileName = tempPdfPath + rs + ".pdf";
if (File.Exists(pdfFileName))
{
File.Delete(pdfFileName);
}
System.IO.File.WriteAllBytes(pdfFileName, bte);
}
else
{
}
}
}
}
API:
[HttpPost]
public async Task<List<SimpleResponse>> Post([FromBody] List<string> request)
{
List<SimpleResponse> responses = new List<SimpleResponse>();
try
{
Converter convert = new Converter();
foreach (string s in request)
{
var result = convert.CovertDocToPDF(s, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);
responses.Add(new SimpleResponse()
{
Result = result,
Success = true
});
}
}
catch (Exception ex)
{
responses.Add(new SimpleResponse()
{
Result = null,
Success = true,
Exception = ex,
Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") }
});
}
return responses;
}

Set the Authentication Token Profile Header

I have an OpenIdConnect Server I'm connecting to an I would like to forward token data the first time logging in to be stored on the server. Currently I'm doing this to forward the access token
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
log(xhr.status, JSON.parse(xhr.responseText));
}
xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
xhr.send();
I want to send the Profile Data as well but I don't know the proper header.
How can I do something like this:
xhr.setRequestHeader("Authorization-Profile", "Bearer " + user.profile);
Does anyone know the proper header so I can add these claims to the access token.
Here is an example of what we did in one of our project:
Created a common API response class as below:
public class ApiCommonResponse
{
public object Object { get; set; }
public int httpStatus { get; set; }
public string httpErrorMessage { get; set; }
}
And a generic method to call GET and POST API endpoints. This method will map the response to the supplied data model and will return you the object.
public static ApiCommonResponse GetApiData<T>(string token, T dataModel, string apiEndPoint = null)
{
var responseText = "";
var apiCommonResponse = new ApiCommonResponse();
if (apiEndPoint != null)
{
var request = (HttpWebRequest)WebRequest.Create(apiEndPoint);
request.Method = "GET";
request.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer " + token);
request.Headers.Add("X-Api-Version", "");
try
{
var httpResponse = (HttpWebResponse)request.GetResponse();
var stream = httpResponse.GetResponseStream();
if (stream != null)
{
using (var streamReader = new StreamReader(stream))
{
responseText = streamReader.ReadToEnd();
}
}
}
catch (WebException we)
{
var stream = we.Response.GetResponseStream();
if (stream != null)
{
var resp = new StreamReader(stream).ReadToEnd();
dynamic obj = JsonConvert.DeserializeObject(resp);
throw new Exception(obj.ToString());
}
}
}
var jsonSettings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore };
apiCommonResponse.Object = JsonConvert.DeserializeObject<T>(responseText, jsonSettings);
apiCommonResponse.httpStatus = 0;
return apiCommonResponse;
}
public static ApiCommonResponse PostApiData<T>(string username, string token, T dataModel, string apiEndPoint = null)
{
var apiCommonResponse = new ApiCommonResponse();
if (apiEndPoint == null) return null;
var webRequest = WebRequest.Create(apiEndPoint);
webRequest.Method = "POST";
webRequest.Timeout = 20000;
webRequest.ContentType = "application/json";
request.Headers.Add("Authorization", "Bearer " + token);
webRequest.Headers.Add("X-Api-Version", "");
using (var requeststreams = webRequest.GetRequestStream())
{
using (var sw = new StreamWriter(requeststreams))
{
sw.Write(JsonConvert.SerializeObject(dataModel));
}
}
try
{
var httpStatus = (((HttpWebResponse)webRequest.GetResponse()).StatusCode);
var httpMessage = (((HttpWebResponse)webRequest.GetResponse()).StatusDescription);
using (var s = webRequest.GetResponse().GetResponseStream())
{
if (s == null) return null;
using (var sr = new StreamReader(s))
{
var responseObj = sr.ReadToEnd();
if (!string.IsNullOrEmpty(responseObj))
{
apiCommonResponse = JsonConvert.DeserializeObject<ApiCommonResponse>(responseObj);
}
}
apiCommonResponse.httpStatus = (int)httpStatus;
apiCommonResponse.httpErrorMessage = httpMessage;
apiCommonResponse.Object = apiCommonResponse.Object;
}
}
catch (WebException we)
{
var stream = we.Response.GetResponseStream();
if (stream != null)
{
var resp = new StreamReader(stream).ReadToEnd();
dynamic obj = JsonConvert.DeserializeObject(resp);
throw new Exception(obj.ToString());
}
}
return apiCommonResponse;
}

C# Xamarin Android Rest call in PCL error "Unexpected character encountered while parsing value: S. Path '', line 0, position 0."

I have used SO to help with several issues in the past. However, I cannot find a solution to something I have been struggling with for 2 days now.
I am a noob, please be kind :)
I have an app that I created using Xamarin Studio, targeted for Android. It is a basic GET request from a Rest Api. It was working perfectly until I realized I was not helping myself when it came time to create the same app in IOS and Windows. Once I changed my project to utilize a PCL I started getting errors, primarily around my RestClient class (originally got from http://www.codeproject.com/Tips/497123/How-to-make-REST-requests-with-Csharp)
From my droid app class:
var apiUser = GetString(Resource.String.apiUser);
var apiPass = GetString(Resource.String.apiPass);
//Get token from API
string token = authenticate(apiUser,apiPass);
public static string authenticate(string apiUser, string apiPass)
{
Authentication Auth = new Authentication ();
try
{
// set json by passing AuthenticationUrl as endpoint, returns json data
var o = JObject.Parse(EntryRepository.getJson(PJTApiUrls.getAuthenticationUrl(apiUser,apiPass)));
Auth.Token = (string)o["Token"];
return Auth.Token;
}
catch (Exception e)
{
// Couldn't do stuff. Log the exception.
// TODO possible timeout, try again, if fails again then return error message
if (e.Message.Contains("400") || e.Message.Contains("401"))
{
string error = string.Format("Invalid credentials, please try again");
return error;
} else {
string error = string.Format ("An error occurred: \r\n{0}", e.Message);
return error;
}
}
}
getAuthenticationUrl gets the api URL.
Here is getJson (in PCL):
public static string getJson(string endpoint)
{
string apiurl = endpoint;
var client = new _RestClient();
client.EndPoint = apiurl;
client.ContentType = "application/json";
client.Method = HttpVerb.GET;
//client.Method = HttpVerb.POST;
client.PostData = "";
//client.PostData = "{postData: value}";
//client.PostData = "{'someValueToPost': 'The Value being Posted'}";
var json = client._MakeRequestAsync();
// to append parameters, pass them into make request:
//var json = client.MakeRequest("?param=0");
return json.ToString();
}
And for the _RestClient class (in PCL):
public async Task<string> _MakeRequestAsync()
{
try {
var request = _MakeRequestAsync ("");
return await request;
}
catch (Exception e){
return e.Message;
}
}
public async Task<string> _MakeRequestAsync(string parameters)
{
var uri = new Uri(EndPoint + parameters);
var request = WebRequest.Create(uri) as HttpWebRequest;
using (var response = await request.GetResponseAsync () as HttpWebResponse) {
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK) {
var message = String.Format ("Request failed. Received HTTP {0}", response.StatusCode);
throw new Exception (message);
}
// grab the response
using (var responseStream = await Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)) {
//using (var responseStream = response.GetResponseStream ()) {
if (responseStream != null)
using (var reader = new StreamReader (responseStream)) {
responseValue = reader.ReadToEnd ();
}
}
return responseValue;
}
}
responseValue is returning null
return await request is saying "Status = Waiting for activation"
I have also had the error: "Unexpected character encountered while parsing value: S. Path '', line 0, position 0."
But this works if the RestClient class is within Droid (Instead of the shared PCL) and contains the following:
public string MakeRequest ()
{
return MakeRequest ("");
}
public string MakeRequest (string parameters)
{
var request = (HttpWebRequest)WebRequest.Create (EndPoint + parameters);
request.Method = Method.ToString ();
request.ContentLength = 0;
request.ContentType = ContentType;
if (!string.IsNullOrEmpty (PostData) && Method == HttpVerb.POST) {
var bytes = Encoding.GetEncoding ("iso-8859-1").GetBytes (PostData);
request.ContentLength = bytes.Length;
using (var writeStream = request.GetRequestStream ()) {
writeStream.Write (bytes, 0, bytes.Length);
}
}
using (var response = (HttpWebResponse)request.GetResponse ()) {
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK) {
var message = String.Format ("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException (message);
}
// grab the response
using (var responseStream = response.GetResponseStream ()) {
if (responseStream != null)
using (var reader = new StreamReader (responseStream)) {
responseValue = reader.ReadToEnd ();
}
}
return responseValue;
}
}
I cannot figure this out, any help/guidance is appreciated. Let me know if I can clarify anything.
***** UPDATE ***** Thanks to #milen-pavlov help thus far, here is where I am currently at:
in Android project:
var apiUser = GetString(Resource.String.apiUser);
var apiPass = GetString(Resource.String.apiPass);
//Get token from API
var token = await authenticate(apiUser,apiPass);
lblOutput.Text = token;
calls (also in Android project):
public static async Task<string> authenticate(string apiUser, string apiPass)
{
Authentication Auth = new Authentication ();
try
{
// set json by passing AuthenticationUrl as endpoint, returns json data
var o = JObject.Parse(await EntryRepository.getJson(PJTApiUrls.getAuthenticationUrl(apiUser,apiPass)));
Auth.Token = (string)o["Token"];
return Auth.Token;
}
catch (Exception e)
{
if (e.Message.Contains("400") || e.Message.Contains("401"))
{
string error = string.Format("Invalid credentials, please try again");
return error;
} else {
string error = string.Format ("An error occurred: \r\n{0}", e.Message);
return error;
}
}
}
Calls json class in PCL project:
public static async Task<string> getJson(string endpoint)
{
string apiurl = endpoint;
var client = new _RestClient();
client.EndPoint = apiurl;
client.ContentType = "application/json";
client.Method = HttpVerb.GET;
client.PostData = "";
var json = await client._MakeRequestAsync();
return json;
}
which then calls restclient class in PCL project:
public async Task<string> _MakeRequestAsync()
{
var request = _MakeRequestAsync ("");
return await request;
}
public async Task<string> _MakeRequestAsync(string parameters)
{
var uri = new Uri(EndPoint + parameters);
using (var client = new HttpClient())
{
var response = await client.GetAsync(uri);
return await response.Content.ReadAsAsync<string>();
};
}
End result/error:
Any guidance is appreciated!
Can you use HttpClient instead?
Sample Get request will look similar to this:
public async Task<string> _MakeRequestAsync(string parameters)
{
var uri = new Uri(EndPoint + parameters);
using (var client = new HttpClient())
{
var response = await client.GetAsync(uri);
return await result.Content.ReadAsStringAsync();
};
}

Post json to xamarin webclient api

I want to post a jsonobject to my webapi. Using normal C# code i would use PostAsJsonAsync on my httpClient object. But that doesn't seem to be supported with xamarin. So my question is how do i post json to my api using xamarin webclient or webrequest?
Here is my code right now that returns null...
protected async override void OnResume()
{
base.OnResume();
var clientRequest = new ResourceByNameRequest
{
Name = "G60",
UserId = "1"
};
HttpContent myContent = new StringContent(clientRequest.ToString());
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("XXX");
var cancellationToken = new CancellationToken();
var response = client.PostAsync("/api/Resource/ResourceByName", myContent, cancellationToken).Result;
var result = await response.Content.ReadAsStreamAsync();
//return result;
}
}
catch (Exception)
{
throw;
}
}
Try something like this:
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
//...
protected override void OnResume()
{
var request = HttpWebRequest.Create("Your_URL_XXX");
request.ContentType = "application/json";
request.Method = "POST";
var clientRequest = new ResourceByNameRequest
{
Name = "G60",
UserId = "1"
};
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(clientRequest.ToString());
}
try
{
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
string error = "";
if (response.StatusCode != HttpStatusCode.OK)
error = string.Format("Error fetching data. Server returned status code: {0} | Description: {1}", response.StatusCode, response.StatusDescription);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if (string.IsNullOrWhiteSpace(content))
{
strResponse = "Response contained empty body...";
}
else
{
var cont = JObject.Parse(content);
YOUR_OBJECT_RESPONSE.PROP1 = cont["Prop1"].NullSafeToString();
YOUR_OBJECT_RESPONSE.PROP2 = cont["Prop2"].NullSafeToString();
//...
}
}
}
}
catch (WebException wex)
{
var pageContent = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();
}
}

Multiple HttpWebRequest in loop?

I have to call web-service multiple time (in loop) the problem is that my code always return empty object (Image Description) and doesn't run properly when I tested it separately (out of loop) it worked normally
here is my portion of code
HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(imageCollection[i].ImageTag));
httpReq.BeginGetResponse(new AsyncCallback((iar) =>
{
try
{
string strResponse = "";
var response = (HttpWebResponse)((HttpWebRequest)iar.AsyncState).EndGetResponse(iar);
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
strResponse = reader.ReadToEnd();
HtmlDocument htmlDocument = new HtmlDocument();
htmlDocument.OptionFixNestedTags = true;
htmlDocument.LoadHtml(strResponse);
HtmlAgilityPack.HtmlNode titleNode = htmlDocument.DocumentNode.SelectSingleNode("//meta[#property='og:description']");
if (titleNode != null)
{
string desc = titleNode.GetAttributeValue("content", "");
imageCollection[i].ImageDescription = desc;
}
}
catch (Exception ex)
{
throw ex;
}
}), httpReq);
httpReq.Abort();
I got the answer from another post in stack-overflow modified to adapt my solution here
Getting the Response of a Asynchronous HttpWebRequest
I made specific class called Request to transform my logic to newly async and await here it's
public Task<string> MakeAsyncRequest()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
Task<WebResponse> task = Task.Factory.FromAsync(
request.BeginGetResponse,
asyncResult => request.EndGetResponse(asyncResult),
(object)null);
return task.ContinueWith(t => ReadStreamFromResponse(t.Result));
}
private string ReadStreamFromResponse(WebResponse response)
{
string desc = "";
try
{
using (Stream responseStream = response.GetResponseStream())
using (StreamReader sr = new StreamReader(responseStream))
{
//Need to return this response
string strContent = sr.ReadToEnd();
HtmlDocument htmlDocument = new HtmlDocument();
htmlDocument.OptionFixNestedTags = true;
htmlDocument.LoadHtml(strContent);
HtmlAgilityPack.HtmlNode titleNode = htmlDocument.DocumentNode.SelectSingleNode("//meta[#property='og:description']");
if (titleNode != null)
{
desc = titleNode.GetAttributeValue("content", "");
}
imageDesc = desc;
return desc;
}
}
catch (Exception ex)
{ return desc; }
}
public string imageDesc { get; private set; }
}
Then I made a Queue of Request
queueWebRequest = new Queue<Request>();
for (int i = 0; i < imageCollection.Count; i++)
{
queueWebRequest.Enqueue(new Request(imageCollection[i].ImageTag));
}
for (int i = 0; i < imageCollection.Count; i++)
{
if (queueWebRequest.Count > 0)
{
Request currentRequest = queueWebRequest.Dequeue();
await currentRequest.MakeAsyncRequest();
imageCollection[i].ImageDescription = currentRequest.imageDesc;
}
else
break;
}

Categories

Resources