Category: C#

Stopping a user from leaving a Silverlight page

Like Flash, Silverlight applications only exist for the life of the page that hosts it.

A common complaint is that when you navigate away from your Silverlight page you get no chance to tidy up or warn the user…

Never fear, help is at hand! All browsers expose an event called window.onbeforeunload.

If you connect a method to that event handler, that returns a string, you will get a standard Message box that looks like this (Internet Explorer):

 

 

or like this (Chrome):

Your javascript  onbeforeclose method is expected to provide a string value to display in that Message box. It makes sense to return that from your Silverlight application, so we will actually kill two birds with one stone.

Here are the actual steps you need to hook into the onbeforeunload event…

1. Add a pluginloaded handler to your HTML page hosting the Silverlight application:

	var slCtl = null;
	function pluginLoaded(sender, args) {
		slCtl = sender.getHost();
	}

This basically stores your Silverlight control object in a global (page) variable called slCtrl.

2. Specify the pluginloaded in your Silverlight object definition:

     <param name="onLoad" value="pluginLoaded" />

This ensures the previous handler is actually called.

3. Define an onClose javascript method and assign it to the onbeforeunload event:

	function onClose() {
		return slCtl.Content.App.OnBeforeClose();
		}
	window.onbeforeunload = onClose

4. Register your Silverlight application object with Silverlight in your App.xaml.cs file Application_Startup event:

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MainPage();
    HtmlPage.RegisterScriptableObject(“App”, this);
}

5. Expose a scriptable method in your application to do the cleanup and return the string to display:
[ScriptableMember]
public string OnBeforeClose()
{
    // Do some shutdown work here…
    return “This is where your custom message will be displayed”;
}

I am assuming you know how to put the Javascript into appropriate HTML script elements in your file.

This is guaranteed to run before the user gets the “Are you sure…” prompt. Just add your “shutdown” processing before you return from OnShutdown and voilà you now have a place to hook your code!

Unfortunately there is no way to stop the Message box, but it is better than your user leaving your Silverlight application before you want them to.

Microsoft Prism 4.0 in pre-release

Prism is a pattern of modular development, used to produce “very large” applications. The current platforms that Prism targets are WPF and Silverlight. Prism was developed by Microsoft and is available to the development public as an open source project here.

The basic premise of Prism is one of divide and conquer. The divide is cleverly performed by using loose coupling of modules (in English that means that modules know little if anything about each other).

Prism includes a practice referred to as Unity. The Unity container is responsible for providing interfaces to modules and objects on request and acts as the central port of call that modules use to communicate with other modules.

There is a very good set of videos giving examples of Prism on the Channel 9 site here.

The latest version combines a second practice known as MEF (Managed Extensibility Framework). This is another Microsoft produced open source project. MEF uses clever techniques to identify requirements in projects, at runtime, by analysing “import” and “export” directives that exist only in the Metadata of the project. MEF is designed to allow for a plug-in style environment, like the Visual Studio IDE.

We are now using Prism and MEF on a medium to large scale project that is expected to have a lifespan of many years.

We will post updates on techniques as we progress on the project. I must say it’s good to be back on hard-core Silverlight development after a spell of APS.Net development.

Thanks, Dave

Using VSTO Excel Smart Tags With Pattern Matching (Regular Expressions)

We are currently developing an Excel Add-in to be used for hostel renting companies.

The existing system we were shown overuses one particular worksheet to contain 10 different columns of rental details, per bed, per day. That results in a very wide worksheet indeed with 1000s of columns. In order to reduce this to a simple bed per date grid of renting/availability the repeated information is extracted to additional worksheets and there will now be one date (column) per bed (row).

Removing such a large amount of needed information from the main worksheet leaves a usability problems: how to easily display and access the associated detail information in a convenient manner.

Excel supports a couple of useful features we can make use of. The first is cell comments. The second is Smart Tags.

Cell Comments

Any cell in a worksheet supports comments. Comments are simple mult-line text entries, shown when you hover over the cell and are ideal for displaying an extra layer of detail. If a comment is present a small red triangle is shown in the top right corner of the cell.

We will use the cell comments to display a copy of all the detail information for that guest booking. Although this adds a lot of duplicate data to the worksheet, it is well worth the overhead to have all the booking details available on every occupied date/bed.

While working on this part of the problem, we found that accessing the comment text string is not well document, but the easiest solution is to call cell.Comment.Text(Type.Missing, Type.Missing, Type.Missing)

Smart Tags

Smart tags are a very cool way of adding context menus that are sensitive to cell content. If a match is found a small purple triangle is shown in the bottom right corner of the cell. The context menus can then provide somewhere to place navigation to related information (e.g. using the cell value as a lookup key).

You have 2 basic choices with Smart Tags. They can have:

  • A list of keywords to match exact words in cells, or (more usefully)
  • A list of regular expressions to match against cell content

We decide to use a contrived system of placing a Guest Id in the bed/date cells of the booking sheet. The Guest Id is of the form yyyymmnnnn. It makes perfect sense to use regular expressions (like @”\d{10}” to match on any number with exactly 10 digits.

A similar contrived system for the beds to rent uses a code of the form roomname-bedletter e.g. G5-A or Flat1-D. In this instance a regular expression of @”\w[\w\d]{0,5}-\w” was used.

Assuming an include like using VSTO = Microsoft.Office.Tools.Excel at the top of the main ribbon .cs file, within the load event of our VSTO ribbon we added code like this:

VSTO.SmartTag guestTag = new VSTO.SmartTag(“http://hitechmagic.com#guest”, “Guest Id”);
guestTag.Expressions.Add(
new System.Text.RegularExpressions.Regex(@”\d{10}”));
Microsoft.Office.Tools.Excel.
Action guestDetailsAction = new Microsoft.Office.Tools.Excel.Action(“Guest details…”);
guestDetailsAction.Click +=
new VSTO.ActionClickEventHandler(guestDetailsAction_Click);
Microsoft.Office.Tools.Excel.Action bookingDetailsAction = new Microsoft.Office.Tools.Excel.Action(“Booking details…”);
bookingDetailsAction.Click +=
new VSTO.ActionClickEventHandler(bookingDetailsAction_Click);
guestTag.Actions = new Microsoft.Office.Tools.Excel.Action[] { guestDetailsAction, bookingDetailsAction };
Globals.ThisAddIn.VstoSmartTags.Add(guestTag); 

 

 

 
Basically this creates a new Smart Tag, adds a regular expression to the list of expressions, sets an array of 2 menu actions as the current actions (each with response events connected), then adds the Smart Tag to the global list of Smart Tags.

 

Results

When we run the add-in with matching values in the cells, we immediately saw little purple triangles on any cells with Guest Id numbers. When we hover over the cell, a little info icon appears beside or below the cell. Clicking the info icon produces a popup (context) menu and clicking the “Guest Details” or “Booking details” options triggers the event handlers you hooked up as expected.

All-in-all our use of Smart Tags went very smoothly and added considerable value for a few hours investigation.

Cheers, Dave

Running multiple websites under N2 CMS

RTFM indeed!

Don’t get me wrong, I really like N2 CMS, but the documentation blows chunks. The number of typos and spelling mistakes in both the online documentation and in the source-code comments is high, but some of the advice given is just plain wrong or out-of-date (which is almost worse than no documentation.. unless you are desperate for ideas). Time for somebody to write a book on N2 CMS… any takers?

The path to enlightenment has many turns

Basically don’t rely on one source of infomation for N2 CMS, use anything/everything you can find. Believe nothing, but try everything! For instance, when attempting to setup multiple website under a single N2 installation I read the single Advanced topic on the N2 site, followed by at least a dozen forum posts:

  • The Advanced topic page incorrectly says to change a “hosts” setting in the web.config, but it is called “host”. Little details like trip up newbie coders all the time.
  • The responses to some posts don’t actually seem to be answering the question asked. Some actually give code examples that are just plain wrong or at least misleading.
  • Multiple N2 websites does require correct setting up of IIS to have multiple domains/subdomains all pointing at the same IIS application.
  • Multiple N2 websites do not work under the Visual Studio debugging webserver. Any domains, aside from the default, are ignored.

How we got it working

  1. Added ISitesSource interface to our HomePage class(es). HomePage is our N2 content class (derived from ContentItem) and used for all our site home pages. You may have different ones per site instead.
  2. Implement a property called Host with an [EditableTextBox] property on any/all home page classes.
  3. Implement a GetSites method that yields an N2.Web.Site(Parent.ID, ID, Host) value on any home page classes. The Host value comes from the previous property we added in step 2. The ID is from the current node and the Parent.ID is the id of the root node that owns the start pages.
  4. Install a local copy of IIS for testing. This is needed as the Visual Studio debug website engine does not support host names (which is required for this feature to work). It means you will have the extra step of publishing your website under IIS to test multi-site functionality. To test one site at a time in Dev Studio just change the initial startPageId in the host setting in web.config.
  5. Add aliases to the hosts file to point any/all test domains at localhost (127.0.0.1)
  6. Publish and install your N2 CMS web site under IIS for your main site, e.g. under a domain called www.YourDomain.com
  7. Ensure that site is running and you can get to the admin interface via /edit
  8. Add additional test sites e.g. sub1.YourDomain.com, but point the physical path of each site at the previous installation directory of the wwwYourDomain.com website. This ensures they all run the same web application, saving memory and sharing code/data.
  9. Run up the admin install, e.g. on www.YourDomain.com/edit/install
  10. Do a normal install, but make sure you add separate root and start nodes for your new site. This is critical as the root must be above all the new sites and each site will have its own start node.
  11. From within the admin interface add extra start nodes to the root node (one for each website you want) and set the Host property of each to its matching domain name (e.g. www.YourDomain.com, sub1.YourDomain.com)
  12. Also put some differing values in the content property of each start node (so you can tell the different sites are working).
  13. Note the ID numbers of each start page, as these have to be listed in the web.config.
  14. Edit the host > sites settings in web.config, adding an entry per hostname/domain. These entries specify which hostnames point to which start nodes when they start.
  15. Now try your various domain/subdomain names under IE (chrome appears to ignore hosts file entries!). If it is working you will see your different start pages under each website.
  16. Give a sigh of relief.

I will pad this out with screen shots and code examples when I get a chance, but thought I should get down the details before I forget :)

Cheers, Dave

Adding a Newsfeed to N2 CMS – Part 2 The XML Feed

Feed me!

A “News feed” is a cool-sounding term that basically means a text file (in a specific format of course). “Text file” does not sound anywhere near so cool.

Where does my feed come from?

That depends… If you have licenced a commercial new feed, like Adfero, you would have been given a URL pointing to your own personal download.

There are various free feeds available too, in varying formats, but I am focusing on the Adfero format for this example.

Adfero format

The Adfero file is an hiearchical XML file. It simply contains multiple Articles, each with multiple Categories and multiple Photos per article.

To process this structure my simplest solution was to create equivalent classes for each major element in the feed file and parse the file hierarchically:

  • FeedArticle
  • FeedCategory
  • FeedPicture*
    • FeedImage

*Note: a FeedPicture represents the picture, a FeedImage represents that picture in a specific size. This way you can process large and thumbnail image details from the feed file the same way.

Each class has enough members to store the incoming XML data and some simple helper getters to return useful items (like caption of 1st image, if any images are present). The classes and members are:

FeedArticle

  • NewsArticleId (int) – News article id (primary key in database)
  • ArticleNumber (string) – Unique article number from feed
  • Heading (string) – Article heading
  • Created (DateTime) – Date/Time article was created
  • Date (DateTime) – Publication date of article
  • Contents (string) – Contents/body or article
  • Summary (string) – Summary of article
  • Caption (string) – Shortcut: get caption of 1st image
  • PictureList (List<FeedPicture>) – List of 1 or more images, each with thumbnail and large
  • CategoryList (List<FeedCategory>) – List of categories for this article
  • LargeImageUrl (string) – Shortcut: get URL of 1st large image
  • LargeImageWidth (int) – Shortcut: get width of 1st large image
  • LargeImageHeight (int) – Shortcut: get height of 1st large image
  • SmallImageUrl (string) – Shortcut: get URL of 1st thumbnail image
  • SmallImageWidth (int) – Shortcut: get width of 1st thumbnail image
  • SmallImageHeight (int) – Shortcut: get height of 1st thumbnail image

FeedCategory

  • Found (bool) – For internal processing use – was this category found in the database (and for the current article)?
  • CategoryId (int) – Unique category id – database PK
  • CategoryNumber (string) – Unique category number (from feed)
  • CategoryName (string) – Display name of category

FeedPicture

  • Portrait (bool) – is the image narrower than tall?
  • AspectRatio (float) – Aspect ratio of width to height of large image
  • PhotoId (int) – Original photo id (from feed)
  • LargeImage (FeedImage) – The large image details (if any)
  • SmallImage (FeedImage) – The small image details (if any)
  • Caption (string) – A text caption for the images

FeedImage

  • ImageURL (string) – Image URL
  • ImageSize (Size) – Size of image
  • Width (int) – Width of image – helper
  • Height (int) – Height of image – helper
  • AspectRatio (float) – Ratio of width to height

Downloading the News feed

The .Net WebClient class is wonderful for downloading content asynchronously. Give it the URL and a local target filename and it does the download for you. If you attach an event hander to the DownloadFileCompleted event, you get informed when the file has been download. This means you now have an XML file on the server, ready to process like any other local file.

Eating the feed

The basic principal of parsing this XML feed follows the hierarchical structure of the feed.

  • Create an XmlTextReader
    • While there are more article nodes
    • Add each processed article to a list of all articles
    • Store the articles in the list

The article processing consists of checking child nodes and either storing attibutes (like Heading, Contents etc), or processing a group of child pictures or child categories. The resulting FeedArticle object is returned:

  • Create a blank FeedArticle
    • While we are processing nodes of the current article
      • if node name is “Heading”, store the value as the article heading
      • if node name is “Date”, store the value as the article date
      • if node name is “Contents”, store the value as the article contents
      • if node name is “Summary”, store the value as the article summary
      • if node name is “Pictures”, process any pictures for this article
      • if node name is “Categories”, process any categories for this article

The picture processing is similar and consists of checking child nodes and either storing attibutes (like PhotoTag etc), or processing a group of child images. The resulting FeedPicture objects are added to the FeedArticle:

  • Create a blank FeedPicture
    • While we are processing picture nodes
      • if node name is “Large”, process an image and store in the large FeedImage
      • if node name is “Small”, process an image and store in the small FeedImage
      • if node name is “PhotoTag”, store the value as the picture caption

The image processing is even simpler and consists only of checking child nodes and storing attibutes (like Width, Height and URL etc) so I will not bother with pseudo-code.

The categories processing consists of processing a group of child category nodes. The resulting FeedCategory objects are added to the FeedArticle.

The category processing (1 category) consists only of checking child nodes and storing attibutes (like ID and the text of the category name) so I will not bother with pseudo-code.

Storing the results

After running these parsing steps you wind up with a hierarchy of objects that you can iterate to run any processing you like. Typically for feed processing you will look for existing entries and see if they are new or changed. If nothing else this allow you to spit out statistics on how many new articles were added or changed from a given day’s feed.

Enough for now, in Part 3 we will look at the merging of the simple article tables, now updated by the previous steps, into the N2 CMS structure. That’s where the fun really begins…

Cheers, Dave

Adding a Newsfeed to N2 CMS – Part 1

Time for something a little more practical…

Adding a 3rd party newsfeed to a CMS is something that many may eventually want to do. Newsfeeds with daily-fresh content can add a lot of SEO value to a website. This basically involves downloading a formatted XML file (e.g. from a company like Adfero) and merging the articles into your CMS, so that they display in your lovely news archives and on your front page (and wherever else you want to see them).

This is the second time I have worked with adding Adfero news feeds to a system, so you can learn from my mistakes without having to make them yourself.

The previous project included a pass-through system, where links were dynamically inserted into the Adfero copy on-the-fly. The links were matched to keywords and phrases. A new URL was provided to clients to pickup the modified newsfeed, now containing hyperlinks embedded into the original articles.

The current project is a bit more straight forward, merging a newsfeed into a CMS system, but built on my knowledge of the previous project.

The secret to merging News feeds into a CMS is  “DO NOT merge the feed directly into the CMS database”. Honestly, there are so many things that can change (possibly even your entire CMS) that you want to keep this process separated into discrete reproducible/testable steps.

Stage 1 processing:

  • Run 1-4 times a day, depending on how lively your newsfeed is.
  • Download the Newsfeed file to a local file.
  • Also allow for specific local file processing as well (so you can restore from XML news archive files)
  • Extract a hierarchy of articles, categories and photos
  • Add new articles, categories and photos to the News tables
  • Update changed articles, categories and photos in the News tables
  • Ignore any completely unchanged articles

The end result of all this is a local database (usually 3 tables) of all past and current articles. Ready for you to do with what you wish!

Stage 2 processing (anytime after step 1):

  • Always run though the stored archive of all articles (does not take long, even for many 1000s).
  • Find the correct parent for the CMS item (there may be more than one… more about this in Part 2).
  • If an existing CMS item exists for an article, and has changed, update that CMS item.
  • If no existing CMS item exists for an article, create a new article.
  • If an existing CMS item exists for an article, and has not changed, do nothing.
  • If the CMS item is under the wrong parent (e.g. it has been deleted) move it back.

Day-to-day-data…

The 3 separate groups of data you will work with are

  • The XML Feed file
  • The local news database tables
  • The CMS database

Best to take this system one chunk at a time. In part 2 we will look at the XML feed format and describe how you can process it in a systematic way. The techniques used can be applied to many types of XML file.

Cheers, Dave

Silverlight at the end of the tunnel!

Don’t let the GUI get you down…

The problem with really complicated websites, is that the interface of a standard HTML based website really lets you down.

We are designing iCollect.it around a very powerful and very scaleable database design. In many ways it is like an Amazon-style database, but with it’s own unique twists.

The requirements for editing content on iCollect.it work well enough in our Site Manager, which is a full-blown Windows application with drag-drop, cut & paste etc, but trying to make the data entry usable on a website is a struggle with established technology. Even our favorite combination of ASP.NET with AJAX still feels sluggish and like we are trapped in the 90′s.

All about timing…

Just last month, Microsoft has released their Azure platform (Microsoft’s cloud computing option). This gives us the massive processing and storage potential we have been waiting for, without having to switch from our prefered C#/.Net combination to Python or another language.

Microsoft’s answer to flash, Silverlight, is now in a stable usuable state with the release of Silverlight 2. The power of Silverlight is in putting desktop-app functionality into a web-browser. The down-side is Silverlight’s current browser support (only about 4 main browsers can run it as of this writing).

What now?

Now we have the necessary “possibilities” covered, we are currently buried up to our necks in Silverlight reference materials and code samples to see how practical it is to turn our crazy ideas into reality.

We can’t find the exact third-party controls we need for iCollect.it, but we have seen enough of what is possible with Silverlight to know we can build our own… One component in particular that we are building for iCollect.it will have such broad appeal that we will likely offer it as a component for other developers. That one should appear publicly in the next few weeks.

Anyway, as I like to say, that website won’t write itself, so I must get back to cutting code.

Keep a lookup for new announcements from us over the Xmas period!

WordPress Themes