WebBrowser and its “gotcha's” – Silverlight 4
Alright, here’s what I learnt tonight while playing with the WebBrowser control in SL4. I built a basic app that looks like this:
You can type the address and click the navigate button or select one of the items in the ‘Fav Links’ listbox to go to the site. The latter method will also populate the url in the textbox. Either way, once the page starts loading, the ‘Navigate’ button and the listbox are disabled until the browser completes loading the page. Pretty basic stuff.
Ok, now my original design was slightly different. I had a ComboBox in the top line of controls and the browser stretched almost to the width of the user control. The problem I was having was that when I did a drop down of the combobox items, the items ‘hid’ themselves behind the webbrowser control. And then I went, ‘Oh yea, Z-Index’ and set the values so that the WebBrowser control had a lower value than the combobox. <InCorrectAnswerBuzz>… that did not work.
This led me to search details about the WebBrowser control. One of the links I hit was this. Although this topic belongs to WPF, I’m guessing this applies for Silverlight as well. SL Experts, please confirm. This forced me to change the design of my application to what it looks like now.
Since version 3, running SL apps as OOB’s is becoming more and more common. While it’s nice and cool to play with once all the coding is done, it’s kind of a pain while you’re still developing/debugging the application. Every time you make some changes to your code, you compile the app, run it in the browser, remove the app, re-install it on your machine and then check if the modifications you made actually work. This is where Laurent Duveau comes for the rescue. His article here tells us how to debug OOB apps. Makes it like taking a ‘walk in the park’ Laurent. Thank you.
But there’s still another part to this. How does the installed version get the version that VS2010 built? That’s where the following code comes for rescue:
1: private void Application_Startup(object sender, StartupEventArgs e)
2: {
3: this.CheckAndDownloadUpdateCompleted += App_CheckAndDownloadUpdateCompleted;
4: // check to see if there's an update available
5: // if yes, download it
6: this.CheckAndDownloadUpdateAsync();
7: this.RootVisual = new MainPage();
8: }
9:
10: void App_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
11: {
12: if (e.UpdateAvailable)
13: {
14: MessageBox.Show("Please restart to use the latest version!", "Application updated",
15: MessageBoxButton.OK);
16: }
17: }
So on every Application_Startup event, the application checks if there’s a latest version of ‘itself’ is available (how very selfish!!). If there is one, the user gets a message and all can update their local version to the latest build.
I was very surprised to see that my own website, which is a SL3 application, breaks when I type the link in the textbox. Now, what I have enabled in my site is for the exception messages to be emailed to me when they occur. Below is the actual message:
Feeds Result: MS.Internal.InternalMemoryStreamMessage: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.
StackTrace: at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl() at System.Xml.XmlTextReaderImpl.ParseDocumentContent() at System.Xml.XmlTextReaderImpl.Read() at System.Xml.XmlReader.MoveToContent() at System.Xml.XmlReader.IsStartElement(String localname, String ns) at System.ServiceModel.Syndication.Atom10FeedFormatter.CanRead(XmlReader reader) at System.ServiceModel.Syndication.SyndicationFeed.Load[TSyndicationFeed](XmlReader reader) at System.ServiceModel.Syndication.SyndicationFeed.Load(XmlReader reader) at AMDotComSL.Page.FeedsReaderClientOpenReadCompleted(Object sender, OpenReadCompletedEventArgs e)
Yes, I do read from feedburner.com to get a list of all the blogs that I’ve written. The message clearly tells me to enable DTD processing in the XmlReader.Create method and MSDN also says:
DTD processing is disabled by default for XmlReader objects created by the Create method.
But, what I don’t get it why it works when I load it regularly, but not through my SL app? Once again, SL Experts, please explain. Update: Per Tim Heuer, the SL Team is looking into this.
The other thing that I get notified about when something goes wrong is the browser type that the user was on. Turns out the WebBrowser control is some wrapper version of IE7. Yes, IE7. Got me thinking, why not IE8? May be the ‘frills’ of IE8, would’ve made the WebBrowser control a lot bigger.. just a speculation. I know I’m making this a habit, but for the last time (for this article), SL Experts, insights please.
Ok, this is probably one of those blog posts that asks more questions than answering them.. hmm that’s odd!! Well, as always, you can download the application code from here.
Hoping to get some answers!!