I am developing a windows phone application. The webclient does not fire as I expected. The related code is as below:
public PArticle(PocketListItem aPli)
{
this.pli = aPli;
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isf.FileExists(aPli.ID + ".json"))
{
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri(pli.Url));
}
else
{
string json = RetrieveDataFromLocalStorage(aPli.ID + ".json");
PocketArticle pa = JsonConvert.DeserializeObject<PocketArticle>(json);
this.text = pa.text;
}
}
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var readability = Readability.Create(e.Result);
this.text = readability.Content;
}
I know it's a synchronous/asynchronous problem. But I have no idea about how to handle it.
Thanks in advance.
I have tested the WebClient part of your code with 2 different URLs http://riktamtech.com and http://google.com. In both cases, the DownloadStringCompleted event is raised. I observed it by placing a break point.
So I suggest you to test again with break points.
Related
I have an image that I need to get from the web, but I need to wait for the image to be downloaded before doing anything else.
So this is my code
BitmapImage bm = new BitmapImage(new Uri(imageUri));
bm.CreateOptions = BitmapCreateOptions.None;
bm.ImageOpened += (sd, args) => {
Debug.WriteLine("loaded");
mre.Set();
};
mre.WaitOne();
Debug.WriteLine(imageUri);
The problem is the code inside ImageOpened event handler never runs. So my program just stops
Is there any way to do this?
You should use WebClient to download web images. Here's an async method:
private Task<BitmapImage> downloadImage(string imageUri)
{
TaskCompletionSource<BitmapImage> tcs = new TaskCompletionSource<BitmapImage>();
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
WebClient wc = new WebClient();
wc.OpenReadCompleted += (s, e) =>
{
if (e.Error == null && !e.Cancelled)
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(e.Result);
tcs.SetResult(bmp);
}
else { tcs.SetResult(null); }
};
wc.OpenReadAsync(new Uri(imageUri, UriKind.Absolute));
return tcs.Task;
}
Here's how to use it:
BitmapImage img = await downloadImage("web url goes here");
if (img == null)
{
//Error handling goes here
}
I'm trying to create a simple app for my phone that can get data from a website and save to the phone. After I looked for, I knew I have to use webClient for this app. When I code I have a problem that set value for a property in a class.
class data
{
public string temp = "";
public void getContent(string url)
{
var client = new WebClient();
client.DownloadStringCompleted += (s, e) => { /*my problem is right here*/};
client.DownloadStringAsync(new Uri(url));
}
}
For example: e.result = "this is a book" so how can I set "e.result" for "temp"?
just replace
client.DownloadStringCompleted += (s, e) => { /*my problem is right here*/};
with
client.DownloadStringCompleted += (s, e) => {
temp = e.Result;
};
I have tried hundreds of times to find errors for this piece of codes.
It only works through WIFI, but When I switch off WIFI on my phone, and run the app again, this app just shut down automatically, which means it thrown an exception.
The app is simple, I used WebClint() to download HTML source and parsed it with HTML Agility Pack, then added them to a list, foreach the list to creat each news object.
I have tried catch the exception stacktrace and bind it to a texblock, It said some of ArgumentOutOfRange exception and Genericlist(int32 index)???
I have no idea about it, It was fine in wifi, but not in 3G network. Can anyone help?
public partial class MainPage : PhoneApplicationPage
{
string srcHTML;
HtmlNode UrlNode;
ObservableCollection<News> newsList = new ObservableCollection<News>();
List<HtmlNode> headlines;
HtmlDocument hd;
News n;
// Constructor
public MainPage()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
WebClient webClenet = new WebClient();
webClenet.Encoding = new HtmlAgilityPack.Gb2312Encoding();
webClenet.DownloadStringAsync(new Uri("http://www.6park.com/news/multi1.shtml", UriKind.RelativeOrAbsolute));
webClenet.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClenet_DownloadStringCompleted);
}
private void webClenet_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
srcHTML = e.Result;
GetHeadlinePage(srcHTML);
}
private void GetHeadlinePage(string srcHTML)
{
hd = new HtmlDocument();
hd.LoadHtml(srcHTML);
try
{
UrlNode = hd.DocumentNode.ChildNodes[1].ChildNodes[3].ChildNodes[8].ChildNodes["tr"].ChildNodes["td"].ChildNodes["ul"];
headlines = UrlNode.Descendants("a").ToList();
foreach (var headline in headlines)
{
if (headline.Attributes["href"].Value.Contains("6park"))
{
n = new News();
n.NewsTitle = headline.InnerText;
n.NewsUrl = headline.Attributes["href"].Value;
n.NewsDetails = headline.NextSibling.InnerText.Replace("- ", "新闻来源:") + headline.NextSibling.NextSibling.InnerText + headline.NextSibling.NextSibling.NextSibling.InnerText;
newsList.Add(n);
}
}
}
catch (Exception ex)
{
//NewsSource.Text = ex.StackTrace + "\n" + ex.Message;
}
NewslistBox.ItemsSource = newsList;
//NewsHeadlineWebBrowser.NavigateToString(ConvertExtendedASCII(headNews));
}
}
I'd debug the value passed to GetHeadlinePage().
I'd suspect that the response is different based on the network or the request is timing out or you're getting some other error.
I'd assume that the call to LoadHtml() is failing as this isn't inside any exception handling/trapping and you've not validating the value passed to it.
I've to download an image from the server on button click.
The code is:
private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).IsEnabled = false;
progressbar.IsIndeterminate = true;
WebClient w = new WebClient();
w.OpenReadAsync(new Uri("http://example.com/xxx/image.png"));
w.OpenReadCompleted += new OpenReadCompletedEventHandler(w_OpenReadCompleted);
}
void w_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
progressbar.IsIndeterminate = false;
BitmapImage b = new BitmapImage();
b.SetSource(e.Result);
Image img = new Image();
img.Source = b;
LayoutRoot.Children.Add(img);
}
The problem which I'm facing is that for the first time the data is being downloaded from the server and shown correctly. However, if I quit the application and again start it, it downloads the old image even if I have deleted the image from the server or changed the image. I think the image is getting cached somewhere but don't know how to solve this problem.
I think this will be the same as your issue:
How do you disable caching with WebClient and Windows Phone 7
I haven't noticed this behaviour when using the HttpWebRequest to get data. But I'am not sure about it.
Update: HttpWebRequest has by default the same behaviour but can be disabled. This blogpost is talking about the options you have:
http://www.nickharris.net/2010/10/windows-phone-7-httpwebrequest-returns-same-response-from-cache/
Finally managed to fix it.The only change that was made is:
w.OpenReadAsync(new Uri("http://example.com/xxx/image.png?q="+Guid.NewGuid()));
You could also use HttpWebRequest to download fresh data every request. Here is a simple class which sets up the asynchronous calls
Here is a simple http client which will download data from the given uri.
public static class HttpClient
{
public static void Execute(Uri uri, Action<HttpWebRequest> onrequest, Action<HttpWebResponse> onresponse)
{
var request = HttpWebRequest.CreateHttp(uri);
onrequest(request);
request.BeginGetResponse
(
result =>
{
try
{
if (request.HaveResponse)
onresponse((HttpWebResponse)request.EndGetResponse(result));
}
catch { }
},
null
);
}
}
Using the HttpClient with your button click event you get this
private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).IsEnabled = false;
progressbar.IsIndeterminate = true;
HttpClient.Execute
(
new Uri(http://example.com/xxx/image.png),
request =>
{
request.UserAgent = "Custom HTTP Client";
},
response =>
{
progressbar.IsIndeterminate = false;
BitmapImage b = new BitmapImage();
b.SetSource(response.GetResponseStream());
Image img = new Image();
img.Source = b;
LayoutRoot.Children.Add(img);
}
);
}
I'm using this to make a web request and download some data:
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
var client = new WebClient();
client.DownloadStringCompleted += (s, e) => {
textBlock1.Text = e.Result;
};
client.DownloadStringAsync(new Uri("http://example.com"));
}
}
The text of textBlock1 never changes even though e.Result has the correct data. How do I update that from the callback?
Edit: If I add MessageBox.Show(e.Result); in the callback along with the textBlock1.Text assignment, both the messsage box and the text box show the correct data.
Edit Again: If I add a TextBox and set it's text right after the line textBlock1.Text line, they both show the correct text.
I think, it's a bug.
I also ran into some problems with updating the UI from different dispatchers. What I finally did was use the TextBlock's (or other UI Element) own dispatcher and that worked for me. I think the phone framework may be using different dispatchers between the app and UI Elements. Notice the change from dispatcher.BeginInvoke to textbox1.Dispatcher...
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var dispatcher = Deployment.Current.Dispatcher;
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
var result = e.Result;
textBlock1.Dispatcher.BeginInvoke(
()=> textBlock1.Text = result
);
};
client.DownloadStringAsync(new Uri("http://example.com"));
}
From browsing through the WP7 forums, a bunch of people were reporting that this was related to a video card driver issue. I've updated my ATI Radeon HD 3400 drivers to the latest version and it appears to work now.
client.DownloadStringAsync is expecting a Uri like this:
client.DownloadStringAsync(new Uri("http://example.com"));
also, shouldn't you update your TextBlock through a Dispatcher.BeginInvoke like this:
client.DownloadStringCompleted += (s, e) =>
{
if (null == e.Error)
Dispatcher.BeginInvoke(() => UpdateStatus(e.Result));
else
Dispatcher.BeginInvoke(() => UpdateStatus("Operation failed: " + e.Error.Message));
};
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var dispatcher = Deployment.Current.Dispatcher;
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
var result = e.Result;
dispatcher.BeginInvoke(
()=> textBlock1.Text = result
);
};
client.DownloadStringAsync(new Uri("http://example.com"));
}
}
I want to comment but can't yet. Yes, I have a very similar issue. In my case it's my viewmodel that is updating a DownloadStatus property, then when the download is completed I do some more work and continue updating this property.
The view stops updating once the ViewModel code hits the OpenReadCompleted method. I've stepped carefully through the code. PropertyChanged fires, and the view even comes back and retrieves the new property value, but never shows the change.
I was sure it was a bug, but then I created a brand new project to reproduce the issue, and it works fine!
Here's a snippet of my non-reproducing code. The UI textblock bound to "DownloadStatus" happily updates properly all the way through. But the same paradigm doesn't work in my main project. Infuriating!
public void BeginDownload(bool doWorkAfterDownload)
{
DownloadStatus = "Starting ...";
_doExtraWork = doWorkAfterDownload;
var webClient = new WebClient();
string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("test:password"));
webClient.Headers["Authorization"] = auth;
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(new Uri("http://www.ben.geek.nz/samsung1.jpg"));
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null)
{
DownloadStatus = e.Error.Message;
return;
}
DownloadStatus = "Completed. Idle.";
if(_doExtraWork)
{
Thread t = new Thread(DoWork);
t.Start(e.Result);
}
}
void DoWork(object param)
{
InvokeDownloadCompleted(new EventArgs());
// just do some updating
for (int i = 1; i <= 10; i++)
{
DownloadStatus = string.Format("Doing work {0}/10", i);
Thread.Sleep(500);
}
DownloadStatus = "Completed extra work. Idle.";
InvokeExtraWorkCompleted(new EventArgs());
}