Use Fulltext Index in AX 2012 to search in RSS feeds

Here is a simple example how to use the fulltext index capability in Dynamics AX 2012. This example downloads RSS postings into a table with fulltext index and runs a query to identify those with specific words.

Create the RssFeedTable

  1. Create a new String Extended Datatype called RssFeedId
  2. Create a new table called RssFeedTable and add the RssFeedId, Name and Uri
  3. Create a primary index based on the RssFeedId
  4. Set the RssFeedTable as Reference at the RssFeedId Extended
  5. Populate the table with data e.g.
    FeedId = technet
    Name = “Technet Austria”
    Uri = http://feeds.feedburner.com/TechnetTeamBlogAustria?format=xml

Create the RssContentTable

  1. Create a new Table called RssContentTable
  2. Add the RssFeedId, Description255 and rename it as Title and a Memo field
  3. Create a fulltext index for the memo field

image image

    Create the RSS Reader Class in C#

    1. Create a new Visual C# class library project for .NET 4.0 in Visual Studio
    2. Add the project to AOT
    3. Copy this code

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel.Syndication;
    using System.Xml;
    using System.Text.RegularExpressions;

    namespace ErpCoder.RssFeed
    {
        public class Reader
        {
            private string xmlAddress = String.Empty;
            private IEnumerator<SyndicationItem> enumerator;

            public Reader(string address)
            {
                xmlAddress = address;
            }

            public void Load()
            {
                var reader = new XmlTextReader(xmlAddress);
                var feed = SyndicationFeed.Load(reader);
                enumerator = feed.Items.GetEnumerator();
            }

            public bool Read()
            {
                return enumerator.MoveNext();
            }

            public string GetTitle()
            {
                return enumerator.Current.Title.Text;
            }

            public string GetDescription()
            {
                string text = Regex.Replace(enumerator.Current.Summary.Text,
                                             "<(.|n)*?>", String.Empty);
                return text;
            }       
        }
    }

    1. Set the Deployment Target at the project to Client: Yes and deploy

    Populate the RssContentTable

    1. Create a find method on the RssFeedTable
    2. Copy this code and substitute the parameter in the find method with one of yours

    static void populateFeedTable(Args _args)
    {
        System.Exception ex;
        RssFeedTable feedTable = RssFeedTable::find("techat");
        RssFeedContent content; 
        ErpCoder.RssFeed.Reader reader;
        InteropPermission permission;
     
        permission = new InteropPermission(InteropKind::ClrInterop);    
        permission.assert();

        try
        {
            reader = new ErpCoder.RssFeed.Reader(feedTable.Uri);
            reader.Load();

            while(reader.Read())
            {
                content.clear();
                content.Title = reader.GetTitle();
                content.Text = reader.GetDescription();
                content.FeedId = feedTable.FeedId;
                content.insert();
            }
        }
        catch(Exception::CLRError)
        {
            ex = CLRInterop::getLastException();
            error(ex.get_Message());
        }

        CodeAccessPermission::revertAssert();
    }

    Create a job to test the fulltext index

    1. Create a new job and copy this code

      static void queryFullText(Args _args)
      {
          RssFeedContent feedContent;
          Query query = new Query();

          QueryBuildDataSource qbdsContent =
           query.addDataSource(tableNum(RssFeedContent));

          QueryBuildRange rangeText =
           qbdsContent.addRange(fieldNum(RssFeedContent,Text),
                                1,QueryRangeType::FullText);
          QueryRun queryRun;
          rangeText.value("Office Hyper-V");

          queryRun = new QueryRun(query);
          while(queryRun.next())
          {
              feedContent = queryRun.get(tableNum(RssFeedContent));
              info(feedContent.Text);
          }
      }

    2. Subsitute the value of the fulltext range value with yours
    3. Test the query

    image

    Add Sound to Infolog

    I’ve been asked by a colleague if it is possible to let the Infolog make a noise depending on the log type, e.g. a *beep* for an info, a *pling* for a warning and an evil noise for an error. Fortunately we can use .NET in AX 2009. The System.Media.SystemSound class already provides access to the typical system sounds. I’ve modified the Info class in AX this way:

    Exception add(
        Exception _exception,
        str _txt,
        str _helpUrl = ”,
        SysInfoAction _sysInfoAction = null,
        boolean buildprefix = true)
    {

        int numOfLines,i;
        int actionClassId;
        container packedAction;
        xSession session;   

        System.Media.SystemSound sound;
        InteropPermission permission;

        ;

    // default infolog code here …

        permission = new InteropPermission(Interopkind::ClrInterop);
        permission.assert();
       
    switch(_exception)
        {
            case(Exception::Info):
            sound = System.Media.SystemSounds::get_Asterisk();
            break;
            case(Exception::Warning):
            sound = System.Media.SystemSounds::get_Hand();
            break;
            case(Exception::Error):
            sound = System.Media.SystemSounds::get_Exclamation();
            break;
        }    
        if(sound!=null)
            sound.Play();

        CodeAccessPermission::revertAssert();

        return super(_exception, (buildprefix?getprefix():”)+_txt);
    }