So basically I have a button. when I click it, two things must occur.
1) a web request to get the data
2) navigate to the other page and populate the data
the problem is that when the app navigates to page2, App.mydirectories gives a nullreferenceException...
How can I make sure App.mydirectories isn't null and wait before populating data to the new page.
private void Button_Click(object sender, RoutedEventArgs e)
{
makeEventwebRequest(number.Text,date.Text);
NavigationService.Navigate(new Uri("/page2.xaml", UriKind.Relative));
}
public void makeEventwebRequest(string numb, string date)
{
string requesturi = string.Format(baseUri, numb, date);
try
{
WebClient client = new WebClient();
client.DownloadStringCompleted +=
new DownloadStringCompletedEventHandler(directories_DownloadStringCallback);
client.DownloadStringAsync(new Uri(requesturi));
}
catch (Exception e)
{
}
}
private void directories_DownloadStringCallback(object sender, DownloadStringCompletedEventArgs e)
{
App.mydirectories = JsonConvert.DeserializeObject<directoriescs>(e.Result);
}
This error occurs because your code to do the WebRequest is async. When you navigate to page2.xaml your data isn't downloaded yet.
This is an example on how you could do your code:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await makeEventwebRequest(number.Text,date.Text);
NavigationService.Navigate(new Uri("/page2.xaml", UriKind.Relative));
}
public async void makeEventwebRequest(string numb, string date)
{
string requesturi = string.Format(baseUri, numb, date);
var request = (HttpWebRequest)WebRequest.Create(requesturi );
var result = await GetHttpResponse(request);
App.mydirectories = JsonConvert.DeserializeObject<directoriescs>(result);
}
// Method helper to Http async request
public static async Task<String> GetHttpResponse(HttpWebRequest request)
{
String received = null;
try
{
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return received;
}
You should read an article on async/await methods like http://msdn.microsoft.com/en-us/library/hh191443.aspx so you can better understand what is different from your code to mine.
The baseline is that you navigated to page2 while the webrequest was still being made, while in the code I posted above, the execution waits for the web request to complete and then navigates to page2.
Related
I want to make a program that checks if the computer is connected to the internet when i start the application.
This is my Form
And this is my Code:
private bool checkinternet()
{
WebRequest request = WebRequest.Create("http://www.google.com");
WebResponse response;
try
{
response = request.GetResponse();
response.Close();
request = null;
return true;
}
catch(Exception)
{
request = null;
return false;
}
}
private void pictureBox1_Click_1(object sender, EvenArgs e)
{
bool checkinternet = false;
{
}
}
The code to check the internet connection works. I tried using buttons, but i want to display an image in imagebox1 if the computer has internet, or display another image if it is not connected.
You need to do the operation in your form load event:
private void Form1_Load(object sender, System.EventArgs e)
{
if (CheckInternet()) // change to upper case (convention for methods)
{
imagebox1.Image = Image.FromFile("p://ath/to/online/image.jpg");
}
else
{
imagebox1.Image = Image.FromFile("p://ath/to/offline/image.jpg");
}
}
The above code is calling your CheckInternet method that returns a bool value whenever there is an internet connection or not.
According to the returned value, you need to set the correct image.
You need to provide the full image path name as parameter to the Image.FromFile method.
First of all you should use a using-directive to automatically dispose your WebRequest:
private bool checkinternet()
{
using(WebRequest request = WebRequest.Create("http://www.google.com"))
{
WebResponse response;
try
{
response = request.GetResponse();
response.Close();
return true;
}
catch(Exception)
{
return false;
}
}
}
Also you need to call your method using braces in an if-statement where you need ==to check for a value:
private void pictureBox1_Click_1(object sender, EvenArgs e)
{
if(checkinternet() == false)
{
//no internet
}
if(checkinternet())
{
//internet
}
if(!checkinternet())
{
//no internet
}
}
Finally, as stated in the answer from ehh you can use the Load event to execute the code when the Form opens:
private void Form1_Load(object sender, System.EventArgs e)
{
if (checkinternet())
{
imagebox1.Image = Image.FromFile("p://ath/to/online/image.jpg");
}
else
{
imagebox1.Image = Image.FromFile("p://ath/to/offline/image.jpg");
}
}
I'm currently working on something, and it requires me to get a new version of the source each time the function is ran. Here is the code so far.
static class DataManager
{
public static async void CollectData()
{
HttpClient client = new HttpClient();
// Call asynchronous network methods in a try/catch block to handle exceptions
try
{
string responseBody = await client.GetStringAsync("http://www.lipsum.com");
ParseHTML(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine("Error: {0}", e.Message);
}
// Need to call dispose on the HttpClient object
// when done using it, so the app doesn't leak resources
client.Dispose();
}
public static void ParseHTML(string _responseString)
{
HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
document.LoadHtml(_responseString);
HtmlAgilityPack.HtmlNode contrib = document.DocumentNode.SelectSingleNode("//*[contains(#class,'randomclass')]");
Console.WriteLine(contrib.InnerText.Replace(",", ""));
}
public static void UpdateLabels(string _timer, string _participants)
{
}
}
I'm wondering if there is a way to make this get a new version of the website each time I run the function.
I'm running it by typing
DataManager.CollectData();
Have you tried:
var client = new HttpClient(new WebRequestHandler() {
CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore)
});
try
{
string responseBody = await client.GetStringAsync("http://www.lipsum.com");
ParseHTML(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine("Error: {0}", e.Message);
}
Have a look at the HttpRequestCacheLevel enum - there are quite a few options that may help you.
I have a simple method which is used to call a WebRequest as demonstrated in the following code. The callback always hits on NetworkError.WebRequestAlreadyFinished. How might I fix my code so that I can get the information from the callback?
private async void stkWebRequestConnInfo_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
HttpWebRequest request = WebRequest.CreateHttp("http://bing.com");
IAsyncResult result = (IAsyncResult)request.BeginGetResponse(new AsyncCallback(response_Callback), request);
}
private void response_Callback(IAsyncResult asyncResult)
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
NetworkInterfaceInfo netInterfaceInfo = null;
try
{
netInterfaceInfo = request.GetCurrentNetworkInterface();
request.EndGetResponse(asyncResult);
}
catch (NetworkException e)
{
// Calling GetCurrentNetworkInterface will throw a NetworkException if the WebRequest has already completed.
// To make this call succeed, make a high latency web request call.
if (e.NetworkErrorCode == NetworkError.WebRequestAlreadyFinished)
{
DisplayMessage(AppResources.MainPage_Info_CannotCallWebRequest, AppResources.MainPage_Info_NetworkInterfaceInformation, MessageBoxButton.OK);
return;
}
else if (e.NetworkErrorCode == NetworkError.NetworkSelectionRequirementFailed)
{
DisplayMessage(AppResources.MainPage_Info_ConnectionRequirementFailed, AppResources.MainPage_Info_NetworkInterfaceInformation, MessageBoxButton.OK);
}
}
catch (WebException e)
{
DisplayMessage(AppResources.MainPage_Info_GeneralError, AppResources.MainPage_Info_WebRequestFailed, MessageBoxButton.OK);
}
// Use a StringBuilder to efficiently build up an information text about this
// NetworkInterfaceInfo.
StringBuilder sb = new StringBuilder();
sb.Append(AppResources.MainPage_Info_Name + " ");
sb.AppendLine(netInterfaceInfo.InterfaceName);
sb.Append(AppResources.MainPage_Info_Type + " ");
sb.AppendLine(GetInterfaceTypeString(netInterfaceInfo.InterfaceType));
DisplayMessage(sb.ToString(), AppResources.MainPage_Info_NetworkInterfaceInformation, MessageBoxButton.OK);
}
void DisplayMessage(string text, string caption, MessageBoxButton buttonConfiguration)
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(text, caption, buttonConfiguration);
});
}
GetCurrentNetworkInterface must be called from the UI thread. So wrap the call with Dispatcher.BeginInvoke();
I'm trying to show a waiting symbol while while a ASYNC task are doing.
I'm really new to this, so if there are better ways to implement this code, please enlighten me :)
But, everything works except the hiding of the pictureBox1 after the code are done and there are now result found. In other words, when there are a result, the pictureBox1 are hidden
Here are the method that runs every time a outlook item are opened
private void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
if (this.OutlookItem is Microsoft.Office.Interop.Outlook.MailItem)
{
Microsoft.Office.Interop.Outlook.MailItem item = (Microsoft.Office.Interop.Outlook.MailItem)this.OutlookItem;
getContactByEmail(item);
}
}
This is the method that I implement the wait stuff
public async Task getContactByEmail(Microsoft.Office.Interop.Outlook.MailItem item)
{
pictureBox1.Visible = true;
using (var client = new System.Net.Http.HttpClient())
{
client.BaseAddress = new Uri("http://api.....");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = await client.GetAsync("tools/getContactByEmail?email=" + item.SenderEmailAddress + "&key=1232");
if (response.IsSuccessStatusCode)
{
SimpleContact contact = await response.Content.ReadAsAsync<SimpleContact>();
lblName.Text = contact.Name;
lblMobile.Text = contact.Phone;
}
pictureBox1.Visible = false;
}
}
Posting the code that fixes this so the exception are not raised
if (response.IsSuccessStatusCode)
{
SimpleContact contact = await response.Content.ReadAsAsync<SimpleContact>();
if (contact != null)
{
lblName.Text = contact.Name;
lblMobile.Text = contact.Phone;
}
pictureBox1.Visible = false;
}
In C# method names are always CamelCase and asynchronous methods are always suffixed Async. Just conventions.
You might want to extract the non UI code to another asynchronous method to avoid going back and forth to the UI thread:
private async void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
if (this.OutlookItem is Microsoft.Office.Interop.Outlook.MailItem)
{
Microsoft.Office.Interop.Outlook.MailItem item = (Microsoft.Office.Interop.Outlook.MailItem)this.OutlookItem;
pictureBox1.Visible = true;
var contact = GetContactByEmailAsync(item);
if (contact != null)
{
lblName.Text = contact.Name;
lblMobile.Text = contact.Phone;
}
pictureBox1.Visible = false;
}
}
public async Task<SimpleContact> GetContactByEmailAsync(Microsoft.Office.Interop.Outlook.MailItem item)
{
using (var client = new System.Net.Http.HttpClient())
{
client.BaseAddress = new Uri("http://api.....");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = await client.GetAsync(
"tools/getContactByEmail?email=" + item.SenderEmailAddress + "&key=1232")
.ConfigureAwait(false);
return (response.IsSuccessStatusCode)
? await response.Content.ReadAsAsync<SimpleContact>();
: null;
}
}
Note: Don't forget proper exception handling!!!
I want to process the http request in thread, the code as follow where the problem is that OutputStream (as noted in codes) can not be writen. When I put this process in main thread, it's no problem. Can you give me any advice?
public partial class MainWindow : Window
{
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var server = new HttpServer();
try
{
server.EndPoint = new IPEndPoint(127.0.0.0, 80); //set webServer para
server.Start(); //start webServer
server.RequestReceived += server_RequestReceived; //register the event
}
catch (Exception ex)
{
return;
}
}
private void server_RequestReceived(object sender, HttpRequestEventArgs e)
{
var dataProcess = new Action<HttpRequestEventArgs>(DataProcess);
Dispatcher.BeginInvoke(dataProcess,e); //start thread
}
private void DataProcess(HttpRequestEventArgs e)
{
StreamReader sr = new StreamReader(#"c:\test.txt");
string text = sr.ReadToEnd();
using (var writer = new StreamWriter(e.Response.OutputStream)) //**Cannot write stream**
{
writer.Write(text);
}
sr.Close();
}
}
I think your request is being close before the new thread runs. What you can do is to execute the whole request in the new thread. Something like:
public partial class MainWindow : Window
{
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var start = new Action<HttpRequestEventArgs>(Start);
Dispatcher.start(start,e); //start thread
}
private void Start(HttpRequestEventArgs e)
{
var server = new HttpServer();
server.EndPoint = new IPEndPoint(127.0.0.0, 80); //set webServer para
server.Start(); //start webServe
server.RequestReceived += server_RequestReceived; //register the event
}
private void server_RequestReceived(object sender, HttpRequestEventArgs e)
{
StreamReader sr = new StreamReader(#"c:\test.txt");
string text = sr.ReadToEnd();
using (var writer = new StreamWriter(e.Response.OutputStream)) //**Cannot write stream**
{
writer.Write(text);
}
sr.Close();
}
}
Most likley e.Response.OutputStream is write-only stream which contains response received from the server.
Depending on what you want to do you may either write to request stream or read from OutputStream.
Note: you are using some custom classes, so suggestion is based purely on method names.