RSS Reader Add-In for the RoleTailored Client

Add-Ins are used to add new features to the RoleTailored Client and was introduced with NAV 2009 SP1.

I have previous written about a ASP.NET RSS reader – in that article, the collection of feeds was a C# function, so why not use this function to extend the RoleTailored Client.

I will be using Visual Studio 2008 to write a Dynamic Link Library (dll), but you can also use the free Express version of Visual C#.

Let’s start by creating a new project – a class library. I have chosen to call it naviRSS.

Add-In libraries must be strong signed, therefor go into properties -> Signing. Here we are going to create a new key.

  • Mark Sign the assemply
  • Chose to create a new strong key
  • Fill the Key file name
        naviRss-StrongKey

Now the signing page should look something like this:

naviRSS-Signing

We have now signed the project, so next is to add the needed references to the project. Add the following references:

  • System.Windows.Forms
  • System.Drawing
  • Microsoft.Dynamics.Framework.UI.Extensibility

Microsoft.Dynamics.Framework.UI.Extensibility is a dll file that usually can be located here: C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client.

Finally we have the initial settings in place and are ready to handle the “real” code.

We will be using 3 items:

  • RssControl.cs
  • RssFeeds.html
  • RssFeeds.cs

Rename the default class1.cs to RssControl.cs (or delete it and create a new one ;-) )

The RssControl will be containing the following functions:

  • public RssControl(string template)
    • is the constructor to handle the integration with RSS Feeds
  • void RssControl_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    • what should happend when the html document is loaded
  • public override string Text
    • updates some variables in the html document
  • private string GetParameter(string parm, string defaultvalue)
    • gets the paramenters which are set from navision
  • private string GetFeed(string rssURL, int maxItems, int showDesc)
    • is the GetFeed functions, that already is known from a earlier article

The complete RssControl.cs will look like this:

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Dynamics.Framework.UI.Extensibility;
using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;
 
 
namespace naviRss
{
 
    public class RssControl : WebBrowser
    {
        private string template;
        private string text;
        private string html = "<html><body></body></html>";
 
        public RssControl(string template)
        {
            this.template = template;
            this.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(RssControl_DocumentCompleted);
        }
 
        void RssControl_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (this.DocumentText != this.html)
            {
                this.DocumentText = this.html;
            }
        }
 
        public override string Text
        {
            get
            {
                return text;
            }
            set
            {
                if (text != value)
                {
                    text = value;
                    if (string.IsNullOrEmpty(value))
                    {
                        html = "<html><body></body></html>";
                    }
                    else
                    {
                        string rss_url = GetParameter("rss_url", "0");
 
                        Int16 no_feeds = 0;
                        Int16.TryParse(GetParameter("no_feeds", "0"), out no_feeds);
 
                        string show_desc = GetParameter("show_description", "1");
 
                        string feeds = "";
                        if (show_desc == "true" || show_desc == "1")
                            feeds = GetFeed(rss_url, no_feeds, 1);
                        else
                            feeds = GetFeed(rss_url, no_feeds, 0);
 
                        html = this.template;
                        html = html.Replace("%rss_url%", rss_url);
                        html = html.Replace("%no_feeds%", no_feeds.ToString());
                        html = html.Replace("%show_description%", show_desc);
                        html = html.Replace("%feeds%", feeds);
                    }
                    this.DocumentText = html;
                }
            }
        }
 
        private string GetParameter(string parm, string defaultvalue)
        {
            foreach (string parameter in text.Split('ยค'))
            {
                if (parameter.StartsWith(parm + "="))
                {
                    return parameter.Substring(parm.Length + 1);
                }
            }
            return defaultvalue;
        }
 
        private string GetFeed(string rssURL, int maxItems, int showDesc)
        {
            string FeedsCollected = "";
 
            System.Net.WebRequest myRequest = System.Net.WebRequest.Create(rssURL);
            System.Net.WebResponse myResponse = myRequest.GetResponse();
 
            System.IO.Stream rssStream = myResponse.GetResponseStream();
            System.Xml.XmlDocument rssDoc = new System.Xml.XmlDocument();
            rssDoc.Load(rssStream);
 
            System.Xml.XmlNodeList rssItems = rssDoc.SelectNodes("rss/channel/item");
 
            string title = "";
            string link = "";
            string pub_date = "";
            string desc = "";
 
            if (maxItems == 0)
                maxItems = rssItems.Count;
 
            if ((maxItems > 0) && (rssItems.Count < maxItems))
            {
                maxItems = rssItems.Count;
            }
 
            for (int i = 0; i < maxItems; i++)
            {
                title = rssItems.Item(i).SelectSingleNode("title").InnerText;
                link = rssItems.Item(i).SelectSingleNode("link").InnerText;
                pub_date = rssItems.Item(i).SelectSingleNode("pubDate").InnerText;
                desc = rssItems.Item(i).SelectSingleNode("description").InnerText;
 
                FeedsCollected += "<a href='" + link + "' target='new'>" + title + "</a><br/>";
 
            }
 
            return FeedsCollected;
        }
    }
 
}

Ok – now we have all the info we need about the feeds. Next is to create a html page, which we will be using to present the feeds with. Add a new item RssFeeds.html to the project.

It is a pretty simple page and could look like this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
	<head>
		<title></title>
	</head>
 
	<body>
        	%feeds%
	</body>
</html>

Notice that we have a variable %feeds%. This variable will be updated by the function Text, that is located in the RssControl.cs.

To be able to use the html page from the RoleTailored Client, we have to embed the file. This is done by adding the resource file Resources.resx to the project.

Then afterwards open Resources.resx and drop (drag & drop) the RssFeeds.html file on it.

Now all we need is to add the item RssFeeds.cs to the project (new item -> class). In RssFeeds.cs we will be handling CreateControl and AllowCaptionControl.

When the NAV Client needs to create the actual winforms control, it will be calling the CreateControl. By having our own CreateControl in the RssFeeds.cs – we are overriding the default method and giving it a html template instead.

AllowCaptionControl is used the override the default handling of captions.

RssFeeds.cs will look like this:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.Dynamics.Framework.UI.Extensibility;
using Microsoft.Dynamics.Framework.UI.Extensibility.WinForms;
using System.Windows.Forms;
 
namespace naviRss
{
 
    [ControlAddInExport("naviRss")]
    public class RssFeeds : StringControlAddInBase, IStringControlAddInDefinition
    {
        protected override Control CreateControl()
        {
            //System.Diagnostics.Debugger.Launch();
            var RssWeb = new RssControl(Resources.RssFeeds);
 
            RssWeb.MinimumSize = new Size(600, 200);
            RssWeb.MaximumSize = new Size(600, 200);
            RssWeb.ScrollBarsEnabled = false;
            RssWeb.ScriptErrorsSuppressed = true;
            RssWeb.WebBrowserShortcutsEnabled = false;
 
            return RssWeb;
        }
 
        public override bool AllowCaptionControl
        {
            get
            {
                return false;
            }
        }
    }
}

[ControlAddInExport(“naviRss”)] is used to set the “control name” for navision. In this case the Control will be known as naviRss.

Everything is now in place and we are ready to build our project.

Build the project and place the naviRss.dll in the Add-Ins directory under the RoleTailored Client.

A little tip – if you don’t want to copy the dll yourself into the Add-Ins directory, then add the following commandline to post-build event commandline in the project properties under “build events”:

copy naviRss.dll “C:\Program Files\Microsoft Dynamics NAV\60\RoleTailored Client\Add-ins”

All you know have to do is setting up the dll in navision and build a page to use it. This will be described in the next article.

You can skip to the end and leave a response. Pinging is currently not allowed.

2 Responses to “RSS Reader Add-In for the RoleTailored Client”

  1. Jarle says:

    Hi. I know it’s not new or anything, but would like to see this working.
    For me it stops with the last class. I’m new into this, so please advice.

    Error 1 The name ‘Resources’ does not exist in the current context C:\tmpsec\naviRSS\naviRSS\RssFeeds.cs 18 40 naviRSS

  2. Ammu says:

    Hi,

    Thanks for the wonderful post.
    The dll doesn’t work in role tailored client. Is it possible for you to send the actual dll file? That can be of great help.

    Thanks,
    Ammu

Leave a Reply


two + 4 =