Json Geocode address parsing in C# - c#

I want to get address of the location
Iam using google geocode to get address by passing lat and long.
static readonly string RequestUrl = "http://maps.google.com/maps/api/geocode/json?";
/// <summary>
/// Gets the raw object.
/// </summary>
/// <returns></returns>
protected JsonGeoData GetJsonObject() {
StringBuilder url = new StringBuilder( GeoRequest.RequestUrl);
if (this.Location != null) {
url.AppendFormat("latlng={0}", this.Location.ToString());
}
else {
url.AppendFormat("address={0}", HttpUtility.UrlEncode(this.Address));
}
url.AppendFormat("&sensor={0}", this.IsSensor.ToString().ToLower());
if (!string.IsNullOrEmpty(this.Language))
url.AppendFormat("&language={0}", HttpUtility.UrlEncode(this.Language));
if(!string.IsNullOrEmpty(this.Region))
url.AppendFormat("&region={0}", HttpUtility.UrlEncode(this.Region));
WebRequest request = WebRequest.Create(url.ToString());
using (WebResponse response = request.GetResponse()) {
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Deserialize<JsonGeoData>(reader.ReadToEnd());
}
}
}
/// <summary>
/// Gets the response.
/// </summary>
/// <returns></returns>
public GeoResponse GetResponse() {
return new GeoResponse(this.GetJsonObject());
}
/// <summary cref="A">
/// fetching location from web
/// </summary>
/// <typeparam name="T"></typeparam>
private string getloc(double plat, double plng)
{
try
{
GeoRequest objreq = new GeoRequest(plat, plng);
GeoResponse objres = objreq.GetResponse();
if (objres.Results.Count > 0)
{ return objres.Results[0].FormattedAddress; }
else
{ return "Unknown"; }
}
catch (FormatException) { return "Unknown"; }
catch (Exception)
{ return "Unknown"; }
}
iam trying to get json data from geocode and parse using serializer,
But iam getting error 'sublocality_level_2 is not a valid value for GeoAddressType.'

Related

Rest transfer non serializable objects

Is there a way to send a non serializable object via Rest ?
I have a request class where some properies can be serialized, but not all.
The class inherits a other class from a SDK (see below 'IWorkflowContext'). This class is protected and can not be serialized - but needs to be transfered. I tried to use JSON, where the non serialization of the SDK object is an issue, when I try to serialize it binary I get a serializer exception
"Request for the permission of type
'System.Security.Permissions.SecurityPermission, mscorlib,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
failed."
My request & serialization looks like this for binary :
byte[] bytes;
IFormatter formatter = new BinaryFormatter();
using (MemoryStream s = new MemoryStream())
{
formatter.Serialize(s, userRequest);
bytes = s.ToArray();
}
stream.Write(bytes, 0, bytes.Length);
And here the Json Serialization
DataContractJsonSerializer ser = new DataContractJsonSerializer(userRequest.GetType());
ser.WriteObject(stream, userRequest);
Or another Json serializers (results in the same non serialization problem)
string json = JsonConvert.SerializeObject(userRequest);
byte[] buffer = Encoding.UTF8.GetBytes(json);
stream.Write(bytes, 0, bytes.Length);
For reference is here my class (modified for binary serialization - for Json I had for each property a Datamember flag.
[Serializable()]
public class AzureRequest
{
public string _orgaName = string.Empty;
public string _connectionString = string.Empty;
public IWorkflowContext _contextWorkflow = null;
public string _webhookOperation = string.Empty;
/// <summary>
/// The Connectionrequest describes a schema to connect to a CRM.
/// e.g. "Url=http://OrgName.crm.dynamics.com/OrgName;AuthType=Office365;Username=UserName#OrgName.onmicrosoft.com;Password=Password";
/// </summary>
public string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
}
}
/// <summary>
/// The Organization Name of the CRM to contact
/// </summary>
public string OrgaName
{
get
{
return _orgaName;
}
set
{
_orgaName = value;
}
}
/// <summary>
/// Is the running Context for the Worklfow instance
/// </summary>
public IWorkflowContext ContextWorkflow
{
get
{
return _contextWorkflow;
}
set
{
_contextWorkflow = value;
}
}
/// <summary>
/// The Operation, the Webhook should perform
/// </summary>
public string WebhookOperation
{
get
{
return _webhookOperation;
}
set
{
_webhookOperation = value;
}
}
}

Handle multiple binding errors from ModelBindingException in NancyFX when binding to JSON in Request.Body

I have a post route that accepts some JSON payload in the request body.
Post["/myroute/}"] = _ =>
{
try
{
var model = this.Bind<MyModel>();
}
catch (ModelBindingException e)
{
//PropertyBindException list is empty here,
//so only the first exception can be handled...
}
}
If there are multiple invalid data types (i.e. if there are several int properties defined in MyModel, and a user posts strings for those properties), I would like pass back a nice list of these errors, similar to how would use ModelState dictionary in a vanilla ASP.NET MVC application.
How can I accomplish this type of exception handling when attempting to bind the JSON payload in the request body to my Model in NancyFX?
Update:
Looking through the DefaultBinder in the Nancy source here:
https://github.com/sloncho/Nancy/blob/master/src/Nancy/ModelBinding/DefaultBinder.cs
The problem I see is that in this block:
try
{
var bodyDeserializedModel = this.DeserializeRequestBody(bindingContext);
if (bodyDeserializedModel != null)
{
UpdateModelWithDeserializedModel(bodyDeserializedModel, bindingContext);
}
}
catch (Exception exception)
{
if (!bindingContext.Configuration.IgnoreErrors)
{
throw new ModelBindingException(modelType, innerException: exception);
}
}
The Deserialize call seems to be "all or nothing" and it is handled by a plain Exception, not a ModelBindException, so I cannot see any PropertyBindExceptions here either.
Should I be needing to implement something custom for this...?
Add your own custom body serializer that uses newtonsoft to ignore errors:
public class CustomBodyDeserializer : IBodyDeserializer
{
private readonly MethodInfo deserializeMethod = typeof(JavaScriptSerializer).GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.Public);
private readonly JsonConfiguration jsonConfiguration;
private readonly GlobalizationConfiguration globalizationConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="JsonBodyDeserializer"/>,
/// with the provided <paramref name="environment"/>.
/// </summary>
/// <param name="environment">An <see cref="INancyEnvironment"/> instance.</param>
public CustomBodyDeserializer(INancyEnvironment environment)
{
this.jsonConfiguration = environment.GetValue<JsonConfiguration>();
this.globalizationConfiguration = environment.GetValue<GlobalizationConfiguration>();
}
/// <summary>
/// Whether the deserializer can deserialize the content type
/// </summary>
/// <param name="mediaRange">Content type to deserialize</param>
/// <param name="context">Current <see cref="BindingContext"/>.</param>
/// <returns>True if supported, false otherwise</returns>
public bool CanDeserialize(MediaRange mediaRange, BindingContext context)
{
return Json.IsJsonContentType(mediaRange);
}
/// <summary>
/// Deserialize the request body to a model
/// </summary>
/// <param name="mediaRange">Content type to deserialize</param>
/// <param name="bodyStream">Request body stream</param>
/// <param name="context">Current context</param>
/// <returns>Model instance</returns>
public object Deserialize(MediaRange mediaRange, Stream bodyStream, BindingContext context)
{
//var serializer = new JavaScriptSerializer(this.jsonConfiguration, this.globalizationConfiguration);
//serializer.RegisterConverters(this.jsonConfiguration.Converters, this.jsonConfiguration.PrimitiveConverters);
if (bodyStream.CanSeek)
{
bodyStream.Position = 0;
}
string bodyText;
using (var bodyReader = new StreamReader(bodyStream))
{
bodyText = bodyReader.ReadToEnd();
}
// var genericDeserializeMethod = this.deserializeMethod.MakeGenericMethod(context.DestinationType);
// var deserializedObject = genericDeserializeMethod.Invoke(serializer, new object[] { bodyText });
object deserializedObject = JsonConvert.DeserializeObject(bodyText, context.DestinationType, new JsonSerializerSettings
{
Error = HandleDeserializationError
});
return deserializedObject;
}
public void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs)
{
string currentError = errorArgs.ErrorContext.Error.Message;
errorArgs.ErrorContext.Handled = true;
}
}

C# Modifying multiple Dictionary Values throws error

I'm using HTML Agility Pack to download some pages, I'm also storing cookie info and login info from a form. The issue I'm having is that I'm doing a GET operation to get the cookie info and form details so on the next step it can login using a username and password, I'm then trying to set the value of the username and password input fields so that I can then post to a login page. The input fields are being stored in a Dictionary<string,string>. I'm able to change one of the dictionary values, but after that I get the error:
"Object reference not set to an instance of an object.".
If I try to change password and then username the username throws the error and vice-versa. This is the code im using:
class Main
{
private void testLogin()
{
BrowserSession b = new BrowserSession();
b.Get("login.html");
b.FormElements["email_address"] = #"email";
b.FormElements["password"] = "password";
string response = b.Post("index.php?main_page=login");
}
}
}
public class BrowserSession
{
private bool _isPost;
private HtmlDocument _htmlDoc;
/// <summary>
/// System.Net.CookieCollection. Provides a collection container for instances of Cookie class
/// </summary>
public CookieCollection Cookies { get; set; }
/// <summary>
/// Provide a key-value-pair collection of form elements
/// </summary>
public FormElementCollection FormElements { get; set; }
/// <summary>
/// Makes a HTTP GET request to the given URL
/// </summary>
public string Get(string url)
{
_isPost = false;
CreateWebRequestObject().Load(url);
return _htmlDoc.DocumentNode.InnerHtml;
}
/// <summary>
/// Makes a HTTP POST request to the given URL
/// </summary>
public string Post(string url)
{
_isPost = true;
CreateWebRequestObject().Load(url, "POST");
return _htmlDoc.DocumentNode.InnerHtml;
}
/// <summary>
/// Creates the HtmlWeb object and initializes all event handlers.
/// </summary>
private HtmlWeb CreateWebRequestObject()
{
HtmlWeb web = new HtmlWeb();
web.UseCookies = true;
web.PreRequest = new HtmlWeb.PreRequestHandler(OnPreRequest);
web.PostResponse = new HtmlWeb.PostResponseHandler(OnAfterResponse);
web.PreHandleDocument = new HtmlWeb.PreHandleDocumentHandler(OnPreHandleDocument);
return web;
}
/// <summary>
/// Event handler for HtmlWeb.PreRequestHandler. Occurs before an HTTP request is executed.
/// </summary>
protected bool OnPreRequest(HttpWebRequest request)
{
AddCookiesTo(request); // Add cookies that were saved from previous requests
if (_isPost) AddPostDataTo(request); // We only need to add post data on a POST request
return true;
}
/// <summary>
/// Event handler for HtmlWeb.PostResponseHandler. Occurs after a HTTP response is received
/// </summary>
protected void OnAfterResponse(HttpWebRequest request, HttpWebResponse response)
{
SaveCookiesFrom(response); // Save cookies for subsequent requests
}
/// <summary>
/// Event handler for HtmlWeb.PreHandleDocumentHandler. Occurs before a HTML document is handled
/// </summary>
protected void OnPreHandleDocument(HtmlDocument document)
{
SaveHtmlDocument(document);
}
/// <summary>
/// Assembles the Post data and attaches to the request object
/// </summary>
private void AddPostDataTo(HttpWebRequest request)
{
string payload = FormElements.AssemblePostPayload();
byte[] buff = Encoding.UTF8.GetBytes(payload.ToCharArray());
request.ContentLength = buff.Length;
request.ContentType = "application/x-www-form-urlencoded";
System.IO.Stream reqStream = request.GetRequestStream();
reqStream.Write(buff, 0, buff.Length);
}
/// <summary>
/// Add cookies to the request object
/// </summary>
private void AddCookiesTo(HttpWebRequest request)
{
if (Cookies != null && Cookies.Count > 0)
{
request.CookieContainer.Add(Cookies);
}
}
/// <summary>
/// Saves cookies from the response object to the local CookieCollection object
/// </summary>
private void SaveCookiesFrom(HttpWebResponse response)
{
if (response.Cookies.Count > 0)
{
if (Cookies == null) Cookies = new CookieCollection();
Cookies.Add(response.Cookies);
}
}
/// <summary>
/// Saves the form elements collection by parsing the HTML document
/// </summary>
private void SaveHtmlDocument(HtmlDocument document)
{
_htmlDoc = document;
FormElements = new FormElementCollection(_htmlDoc);
}
}
public class FormElementCollection : Dictionary<string, string>
{
/// <summary>
/// Constructor. Parses the HtmlDocument to get all form input elements.
/// </summary>
public FormElementCollection(HtmlDocument htmlDoc)
{
var inputs = htmlDoc.DocumentNode.SelectSingleNode("//div[#id = 'loginDefault']").Descendants("input");
foreach (var element in inputs)
{
string name = element.GetAttributeValue("name", "undefined");
string value = element.GetAttributeValue("value", "");
if (!name.Equals("undefined")) { Add(name, value); }
}
}
/// <summary>
/// Assembles all form elements and values to POST. Also html encodes the values.
/// </summary>
public string AssemblePostPayload()
{
StringBuilder sb = new StringBuilder();
foreach (var element in this)
{
string value = HttpUtility.UrlEncode(element.Value);
sb.Append("&" + element.Key + "=" + value);
}
return sb.ToString().Substring(1);
}
}
Any help would be much appreciated.
While debugging put a break point after calling the b constractor.
You ll find the FormElements property is Null.
You need to inialize it in BrowserSession constractor.

Why can I still write to session when SessionStateBehavior.ReadOnly is set on a controller and should I care?

I have a number of controllers with SessionStateBehavior.ReadOnly set on them to enable parallel processing of multiple ajax requests.
But I have noticed that this doesn't stop me from writing to session (unlike SessionStateBehavior.Disabled which throws an exception).
My application uses Microsoft Charting and the chart and image map are generated in response to an ajax request with the chart being stored in session until the image markup is rendered by the browser at which point the image src triggers the browser to request the chart image which is retrieved from session. So there are no issues here with attempting to read from session before its been written.
Everything works fine, I have multiple ajax requests being processed in parallel and my charts are being returned correctly so does it matter that I have declared SessionStateBehavior.ReadOnly when I am writing to session?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Web.UI.DataVisualization.Charting;
using Mdl.Rcm.Web.Areas.Dashboards.Models;
using Mdl.Web.Security;
using Mdl.Persistence.UoW;
using Mdl.Rcm.Business.Dashboards;
using Mdl.Rcm.Business.Dashboards.Models;
using Mdl.Rcm.Web.Areas.Dashboards.Charts;
using Mdl.Rcm.Web.Areas.Dashboards.Charts.OrganisationConnectionsByRole;
using Mdl.Web.Mvc;
namespace Mdl.Rcm.Web.Areas.Dashboards.Controllers
{
/// <summary>
/// Controller for the Organisation Connections By Role chart.
/// </summary>
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
[RedirectingAuthorize(Roles = "Dashboards")]
[Area(IsSiteRoot = false)]
public class ChartOrganisationConnectionsByRoleController : Controller
{
private readonly IRelationshipAndRiskService relationshipAndRiskService;
private readonly IConfigurationService configurationService;
private readonly IOrganisationConnectionsByRoleChartBuilder chartBuilder;
private readonly IListService listService;
private BarConfiguration barConfiguration;
private const string TempDataKey = "OrganisationConnectionsByRoleData";
public ChartOrganisationConnectionsByRoleController(IOrganisationConnectionsByRoleChart organisationConnectionsByRoleChart, IRelationshipAndRiskService relationshipAndRiskService, IConfigurationService configurationService, IOrganisationConnectionsByRoleChartBuilder chartBuilder, IListService listService)
{
this.relationshipAndRiskService = relationshipAndRiskService;
this.configurationService = configurationService;
this.chartBuilder = chartBuilder;
this.listService = listService;
}
/// <summary>
/// Standard Organisation Connections by Role component loader
/// </summary>
/// <param name="listId">The list id.</param>
/// <param name="degree">The active degree.</param>
/// <param name="barIndex">Index of the active bar.</param>
/// <returns></returns>
[HandleAjaxError]
public ActionResult Load(int listId, int degree, int barIndex)
{
using (UnitOfWork.Start("Analysis"))
{
// Get the data
var relationshipPlanningData = GetChartDataForInitialLoadParentComponent(listId);
var connectionsFound = relationshipPlanningData.SeriesModels.Count > 0;
var listName = listService.GetListName(listId).Name;
var information = new InformationModel(degree, true) { ConnectionsFound = connectionsFound, NumberOfOrganisationsInList = relationshipPlanningData.TotalNumberOfOrganisations, ListName = listName };
return PartialView("OrganisationConnectionsByRoleComponent", new OrganisationConnectionsByRoleComponentModel { ListId = listId, ActiveDegree = degree, ActiveBarIndex = barIndex, BarConfiguration = configurationService.GetBarConfiguration(), ConnectionsFound = connectionsFound, Information = information});
}
}
/// <summary>
/// Creates the Connections by Role chart and stores it in Session then returns the chart map.
/// The chart image map is always created first, the chart is created as part of the process of creating the map.
/// </summary>
/// <returns></returns>
public ActionResult Chart(Guid chartId, int listId)
{
using (UnitOfWork.Start("Analysis"))
{
barConfiguration = configurationService.GetBarConfiguration();
var relationshipPlanningData = GetChartDataForInitialLoadChart();
if (relationshipPlanningData.SeriesModels.Count == 0)
{
return PartialView("InfoMessage", "No connections found");
}
// Set up the chart
return GenerateChart(relationshipPlanningData, listId, chartId);
}
}
private ActionResult GenerateChart(OrganisationConnectionsByRoleData relationshipPlanningData, int listId, Guid chartId)
{
var chartAndXPoints = chartBuilder.BuildChart(2, relationshipPlanningData, barConfiguration, SetActiveBarIndex(-1), listId);
// Store the chart in session for retrieval by the browser as the src on an image tag.
ChartSession.GenerateChartToSession(chartId, chartAndXPoints.Chart, Session);
// Get y data for use client side
var yPointsDataView = GetYPointsDataView(relationshipPlanningData);
// Get x co-ordinates for use client side. Must be done after the chart has been generated to session.
var xPointsView = GetXPointsView(chartAndXPoints.XPoints);
// Render the image tag and image map
return this.Chart(chartAndXPoints.Chart, xPointsView + yPointsDataView, chartId, "ConnectionsByRoleImage");
}
/// <summary>
/// Gets the chart data for use by the main component.
/// </summary>
/// <param name="listId">The list id.</param>
/// <returns></returns>
private OrganisationConnectionsByRoleData GetChartDataForInitialLoadParentComponent(int listId)
{
// This is the call from the load action so get the data and store it for use by the chart action to save the performance hit
var data = relationshipAndRiskService.GetOrganisationConnectionsByRoleChartData(listId);
TempData[TempDataKey] = data;
return data;
}
/// <summary>
/// Gets the chart data for use by the main component chart.
/// </summary>
/// <returns></returns>
private OrganisationConnectionsByRoleData GetChartDataForInitialLoadChart()
{
// This call is from the chart action so use the data that was retreived on the load action
return (OrganisationConnectionsByRoleData)TempData[TempDataKey];
}
/// <summary>
/// Return the Connections By Role chart from session.
/// </summary>
/// <returns></returns>
public ActionResult ConnectionsByRoleImage(Guid chartId)
{
var chart = ChartSession.GetChartFromSession(chartId, Session);
return File(chart, "image");
}
/// <summary>
/// Return the Connections By Role chart from session.
/// </summary>
/// <param name="listId">The list id.</param>
/// <param name="degree">The active degree.</param>
/// <param name="barIndex">Index of the active bar.</param>
/// <returns></returns>
public ActionResult ConnectionsByRoleActive(int listId, int degree, int barIndex)
{
using (UnitOfWork.Start("Analysis"))
{
barConfiguration = configurationService.GetBarConfiguration();
// Get the data
var relationshipPlanningData = relationshipAndRiskService.GetOrganisationConnectionsByRoleChartData(listId);
if (relationshipPlanningData.SeriesModels.Count == 0)
{
return PartialView("InfoMessage", "No connections found");
}
// Set up the chart
var chartAndXPoints = chartBuilder.BuildChart(SetActiveDegree(degree), relationshipPlanningData, barConfiguration, SetActiveBarIndex(-1), listId);
var ms = new MemoryStream();
chartAndXPoints.Chart.SaveImage(ms, ChartImageFormat.Png);
return File(ms.ToArray(), "image");
}
}
/// <summary>
/// Gets the graph X points and render them as a javascript object for use by the view.
/// </summary>
/// <param name="xPoints">The x points.</param>
/// <returns></returns>
private string GetXPointsView(List<float> xPoints)
{
var model = new XPointsModel
{
ChartName = "Connections By Role",
Points = xPoints
};
return this.ViewAsString("XPoints", model);
}
/// <summary>
/// Gets the Y points data and render them as a javascript object for use by the view.
/// </summary>
/// <param name="relationshipPlanningData">The relationship planning data.</param>
/// <returns></returns>
private string GetYPointsDataView(OrganisationConnectionsByRoleData relationshipPlanningData)
{
var degree1DataPoints = relationshipPlanningData.SeriesModels[0].DataPoints.Select(p => p.Y).ToList();
var degree2DataPoints = relationshipPlanningData.SeriesModels[1].DataPoints.Select(p => p.Y).ToList();
var model = new YPointsDegree1And2Model
{
ChartName = "Connections By Role",
Degree1Data = degree1DataPoints,
Degree2Data = degree2DataPoints
};
return this.ViewAsString("YPointsDegree1And2", model);
}
private int SetActiveBarIndex(int barIndex)
{
if (barIndex == -1)
{
barIndex = barConfiguration.Bars.First(b => b.IsDefaultActive).Index;
}
return barIndex;
}
private static int SetActiveDegree(int degree)
{
if (degree == -1)
{
degree = 2;
}
return degree;
}
}
}
public class ChartSession
{
public static byte[] GetChartFromSession(Guid chartId, HttpSessionStateBase session)
{
// Get the chart from session
var data = session[chartId.ToString()] as byte[];
// Clear the session
session[chartId.ToString()] = null;
return data;
}
public static void GenerateChartToSession(Guid chartId, Chart chart, HttpSessionStateBase session)
{
var ms = new MemoryStream();
chart.SaveImage(ms, ChartImageFormat.Png);
session[chartId.ToString()] = ms.ToArray();
}
SessionStateBehavior only tells ASP.NET what locks to put on the Session
See this question: Controller SessionStateBehavior is ReadOnly and I can update Session Variable

Why is list Empty?

I am able to access the list (ListData) value from within its class, but if I try to reference the list from outside of the class, it shows it as an empty list.
I add objects to ListData in the getVideoList method.
I added this piece of code and it works now (Polling method) , Is this ineffiencient ?
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(getVideoList), state);
while (result.IsCompleted == false)
{
Thread.Sleep(1000);
}
Public class otherclass{
static void main(string [] args){
RestProcess process = new RestProcess(videoListURI);
process.initilaizeRest();
foreach (VideoSeriesElement ele in process.ListData)
{
Console.WriteLine(ele.id);
Console.WriteLine(ele.title);
Console.WriteLine(ele.href);
Console.WriteLine(ele.image);
}
Console.ReadLine();
}
}
public class RestProcess
{
/// <summary>
/// Default constructor
/// </summary>
///
readonly string blankimage = "http://images1.test.com/properties/NoThumbnail_HD.jpg";
public RestProcess(string uri)
{
URI = uri;
ListData = new ObservableCollection<VideoSeriesElement>();
}
public ObservableCollection<VideoSeriesElement> ListData{get;set;}
public void initilaizeRest()
{
WebRequest request = HttpWebRequest.Create(URI);
request.Method = "GET";
// RequestState is a custom class to pass info to the callback
RequestState state = new RequestState(request, URI);
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(getVideoList), state);
}
public string URI{get;set;}
/// <summary>
/// getVideoList
/// </summary>
/// <param name="result"></param>
public void getVideoList(IAsyncResult result)
{
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.Request;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
try
{
TextReader textreader = new StreamReader(response.GetResponseStream());
XDocument doc = XDocument.Load(textreader);
foreach(XElement videoSeriesEle in doc.Descendants("video-series"))
{
var videseriesEle = new VideoSeriesElement();
videseriesEle.id = videoSeriesEle.Attribute("id").Value;
videseriesEle.href = videoSeriesEle.Attribute("href").Value;
videseriesEle.title = videoSeriesEle.Element("title").Value;
if (!videoSeriesEle.Element("images").IsEmpty && videoSeriesEle.Element("images").Elements("image") != null)
{
var imagelist = videoSeriesEle.Element("images").Elements("image").ToList();
foreach (var ele in imagelist)
{
if (ele.Attribute("styleid").Value.Equals("5"))
{
if (videoSeriesEle.Element("images").Element("image").Attribute("href").Value != null)
{
videseriesEle.image = videoSeriesEle.Element("images").Element("image").Attribute("href").Value;
}
}
}
}
else { videseriesEle.image = blankimage; }
//add object to list
ListData.Add(videseriesEle);
}
//Close streams
textreader.Close();
response.Close();
}
catch (XmlException e)
{
Console.WriteLine(e);
}
}
/// <summary>
///
/// </summary>
/// <param name="state"></param>
/// <param name="timedOut"></param>
private static void ScanTimeoutCallback(object state, bool timedOut)
{
if (timedOut)
{
RequestState reqState = (RequestState)state;
if (reqState != null)
reqState.Request.Abort();
Console.WriteLine("aborted- timeout");
}
}
}
The RestProcess.initilaizeRest() method requests the data via an IAsyncResult, meaning the call to get the data is asynchronous. In your otherClass class, you attempt to process and loop through the ListData element immediately after calling initilaizeRest() and there is a very good chance that the data is not loaded yet.
To fix this, you should have a callback/event-handler in the otherClass that listens for when the data is populated.
You can expose IAsyncResult result as a property from the request.BeginGetResponse call in RestProcess and block in otherClass until the IAsyncResult.IsCompleted property is true, or use the WaitHandle exposed by it, but is there a reason that you're using the async BeginGetResponse call rather than the synchronous GetResponse call?

Categories