Designing a mobile RSS 2.0 feed reader app that uses a Cross Media Data Relation

This is the second post of a series of blog posts about new Data Relations feature in DirectSmile Cross Media.

In the previous post I explained who create a Data Relation that consumes an RSS 2.0 Feed. In the second and third part of the series I show how we can design a mobile application that uses the Data Relation.

Design

All the data relation needs is a URL to the feed provider. Having this in mind I will create a mobile application that contains basically two pages.

image

The first page should show a few buttons to present a selection of RSS feeds. In this example I choose some news channels.

Selecting one of those channels will lead me to a new page that shows a list of items of the feed I selected.

image

Let’s say I selected the DirectSmile Blog RSS feed (which is the button with in the upper right corner in the example) then I will see a list of the latest DirectSmile blog posts.

Because the RSS 2.0 sepefication supports media content it’s easy to show images as well.

To top this we could also check the media content type, and if it’s audio (like in the .Net Rocks RSS feed in the example is providing) we could show a HTML5 audio player.

image

The media content type is field in the Data Relation, so it’s easy for us to setup a condition that takes advantage of this later on in the designer.

Application structure diagramm

Here’s a diagramm to better explain the workflow of the sample application.

image

Next

In the next part of this series I will show you how to build this application using the DirectSmile Cross Media Designer.

Have fun,

Oliver

Advertisements

DSMX Data Relation to consume RSS 2.0 feeds 1/2

A Data relation that consumes an RSS 2.0 XML data stream is pretty straight forward to implement. All it needs is basically an URL pointing to the RSS Feed provider and a .net WebClient object that downloads the XML from the server and deserializes it into a data relation table.

But let’s start by implementing the data relation. To do so, create a new class library project in Visual Studio, doesn’t matter if C# or VB.NET, I’m using vb.

Add a reference to the DataRelationInterfaces.dll and create a new class, named RssFeedRelation, which implements IDataRelation.

GetMetaData

The GetMetaData method is called by DSMX to get metadata information from the relation. This is where we add two tables, one that will provide basic information like link, description and name of the RSS feed. A second table that contains a list of all available RSS feed items.

We also want to add to parameters, one for the server URL and another for the provided encoding. Because in most cases the encoding is utf-8, we set this as the default. I also added a default for the Feed URL as well.

Public Sub GetMetaData(ByVal accountID As Integer, ByVal Language As String, ByVal MetaData As IhtDataProviderMetaData) Implements IDataRelation.GetMetaData
     MetaData.AddTable(RssFeedPropertiesTable)
     MetaData.AddTable(RssFeedTable)
     MetaData.AddParameter("Encoding", "RSS Feed XML content encoding", "utf-8", False)
     MetaData.AddParameter("RssFeedUrl", "Url pointing to the RSS feed XML.", "http://support.directsmile.de/support/rss.aspx", False)
End Sub

LoadData

Implementing the LoadData method that is actually called by DSMX to get the feed data is also no black magic at all.

 Public Sub LoadData(ByVal table As IhtDataTable) Implements IDataRelation.LoadData
        Dim url As String = table.GetParameterValue("RssFeedUrl")
        Dim enc As String = table.GetParameterValue("Encoding")
        If table.Query.TableName = RssFeedTable Then
            AddFeedItemTableFields(table)
            Dim itms = LoadFeedItems(url, enc)
            If Not itms Is Nothing AndAlso itms.Count > 0 Then
                Dim pagedResult As IEnumerable(Of RssItem) = GetPagedResultSet(table, itms)
                AddFeedItems(table, pagedResult)
            End If
        ElseIf table.Query.TableName = RssFeedPropertiesTable Then
            AddFeedPropertiesTableFields(table)
            Dim itms = LoadFeedItems(url, enc)
            If Not itms Is Nothing AndAlso itms.Count > 0 Then
                AddFeedProperties(table, itms)
            End If
   Else
            Throw New ArgumentException("No valid table name found.")
End If

That method does two things, first it checks what table was requested by DSMX. It contacts the Feed providing server and downloads the feed XML to return either the list of items or just the feed header.

LoadItems

The LoadItems method instanciates a WebClient and downloads the XML.

Public Function LoadFeedItems(url As String, enc As String) As IEnumerable(Of RssItem)
        If String.IsNullOrEmpty(url) Then
            Throw New ArgumentException("RSS feed URL must have a value.")
        End If
        Dim wc As New WebClient()
        wc.Encoding = Encoding.GetEncoding(enc)
        Dim result = wc.DownloadString(New Uri(url))
        If String.IsNullOrEmpty(result) Then
            Throw New ArgumentException("RSS feed URL returned no valid RSS data [" & url & "]")
        End If
        Dim rssFeedItems = New RssItems
        rssFeedItems.Deserialize(result)
        Return rssFeedItems
End Function

If the download was successful we can deserialize the XML data into a CLR object. Very convenient using XML literals in VB.NET.

Public Sub Deserialize(xml As String)
        If String.IsNullOrEmpty(xml) Then
            Throw New ArgumentException("Feed xml contains to data.")
        End If
        Dim doc As XDocument = XDocument.Parse(xml)
        If doc Is Nothing Then
            Throw New Exception("Failed to parse rss feed xml.")
        End If
        Title = doc...<channel>.<title>.Value
        Link = doc...<channel>.<link>.Value
        Description = doc...<channel>.<description>.Value
        For Each elem In From element In doc...<channel>.<item>
            If elem.Name = "item" Then
                Add(New RssItem With {.Author = elem.<author>.Value,
                                      .Description = elem.<description>.Value,
                                      .Link = elem.<link>.Value,
                                      .PubDate = TryConvertToDate(elem.<pubDate>.Value),
                                      .Title = elem.<title>.Value,
                                      .EnclosureUrl = elem.<enclosure>.@url,
                                      .EnclosureType = elem.<enclosure>.@type})
            End If
        Next
End Sub

Conclusion

Basically that’s all it needs to consume RSS feeds. In part 2 of this short series I will create a little mobile RSS feed reader to show you easy it is to integrate this data relation into a cross media server.

Have fun

Oliver

Creating a DirectSmile Cross Media mobile application that consumes a Data Relation

This is the third post of a series of blog posts about new Data Relations feature in DirectSmile Cross Media.

In the last two posts I described how to create a Data Relation programmatically and showed how to test the Data Relation using the Data Relation Test Environment. In this post I will show how to create a mobile PURL website that consumes the Data Relation to let us search for movies in the Amazon store.

The sample campaign will contain of two mobile pages. The first page provides a search field for a title and a list of movies. If we select one of the movies from the list we will be redirected to page that shows the details of the movie, like the synopsis and the cast.

Setting up the campaign

First I open the Designer and select Create new campaign. I call the campaign MovieSearch and start with the default database. Later on I’ll drop that and replace it with a tiny database that suites better my needs.

image

In the following dialog I select a Static mobile page and name it Search.

image

Adding the Data Relation

Now I replace the default database with a short, but more meaningful, database. I’m using a CSV file I created with Microsoft Excel. That “database” contains a single table with a single column called title, and some movie titles to play with.

image

After replacing the database we can add our Data Relation. To add a Data Relation I select Add Data Relation from the Database menu.

image

Then I select the Amazon Movie Search Data Relation from a list of available Data Relations. Because of the plugin structure this list can contain more or less different Data Relations by the way.

image

After I have selected to Data Relation I will be asked to provide the values for the preassigned parameters, in our case the Amazon Developer credentials and a default value for the search title.

image

Finally I can change the name of Data Relation or the table where to store the Data Relation in, but there is no need to change this and close the wizard.

image

Now, that the Data Relation is assigned, my Designer window looks like this.

image

In the bottom of the Designer window you can find the Data Relation, showing already some results, because we predefined the title parameter with the search title Green Lantern.

Adding some controls

First I need a text box to enter movie titles. I set the caption to Movie Title and assign the value of the text box to [[Title]] database field.

image

Next I add a button that does the search, in other words it will query the Data Relation with the search term typed into the search text box.

image

Interesting here is, that we don’t want to leave this mobile page when we hit the button, but we want to show a list of search results instead. We do that by utilizing the Register new User function and link to the same page again.

Finally we add a data list control and select of Data Relation as data source.

image

In the moment we don’t have a second page to show the details to the movie, but that will be the next setp. So far, we assign the AmazoonSearchResult.Name property to the caption to show the movie title and select the AmazonSearchResult:MediumImageUrl property as the value of the data list image. The Link value doesn’t matter in the moment and I select just the same value like this:

image

Although that we didn’t do very much, the result is already quite impressing and our preview looks like this:

image

Details page

Now we need to add a second page, this time a personalized mobile page, to show the details of the selected movie. I call this second page SearchResults.

image

This page contains just a bunch of controls showing the values from our Data Relation data source for a specific movie. Typically an image that shows the movie, the title, the cast and director and more…

image

Now that we have our details page, we can go back to the Search page and customize the link property of the data list item.

image

I configure the link to be internal, check the submit button and select Submit Data to ensure that the data of the selected movie is transfer to the second page, which also select to SearchResult.html.

Finally, to avoid that our first page call produces an error, because we don’t deliver a title, we define a default value for the title property in the data relation, like this:

image

That filter takes the value of the Title field if it’s not empty or it takes “Batman” if the Title field value is empty.

Previewing the application

Previewing the campaign is easily done by clicking the world icon in the uppor right corner of the designer. If your browser does not open a new window, please check if your browser is blocking pop-up windows and allow pop-ups for this Designer’s domain.

image

Hey, that looks good so far. We can type in a title and search Amazon for a list of Futurama movies.

image

And if we click on one of the list items the SearchResults page is called and shows the movie details.

I hope this is helpful to get started with DirectSmile Cross Media Data Relations.

Have fun,

Oliver

Documentation of Cross Media data relations

This is the second post of a series of blog posts about new Data Relations feature in DirectSmile Cross Media.

Documentation

I’m very excited to to let you know that we added a new web based documentation center for DSMX Data Relations, what can be found here:

DSMX Data Relations

This help web site contains a download link for the documentatation and a full featured sample Data Relation project for Microsoft Visual Studio. It also provides a sample database needed for the data relation.

You can also download the Data Relations Test Environment from this web site. The Test Environment is a windows application to test your data relation and data source indepently from the DSMX Designer, what is quite handy while the development process.

Testing the Amazon Data Relation using the Test Environment

The Test Environment comes with a ClickOnce installation executable. Please run the setup.exe file to install the application. The application starts automatically after the installation is finished. Important is to check the default location for the DLL-Plugin-Path (i.e. the path where you need to place your Data Relation plugin assembly).

image

Typically the folder is located in a subfolder of the AppData directory. Just drop your Data Relation dll into the folder and restart the Test Environment.

Your Data Relation should now be visible in the Data Relations list.

image

All you need to do now is to select your Data Relation and type in the developer credentials needed for our Amazon web service sample.

image

TIP: You can create a text file that contains default values for your parameters. This file must be named like the Data Relation and located in the same folder and the file extension must be *.txt. This is very helpful while debugging, because the parameters are not persisted in the application.

Here’s a sample of the AmazonRelation.txt parameter file:

AWSSKeyId: YOUR IDGOES HERE;
AWSSecretKey: YOUR KEY GOES HERE;

Names and values are seperated by a colon and each Key/Value pair is finalized by a semicolon.

Having fun coding a DirectSmile Cross Media Data Relations

The Crossmedia version 5 comes with many new features and today I picked one that totally thrills me. Actually, I think that it’s way too cool to name it Data Relations, what is rather obfuscating the real power of this new feature. To show you why I figure Crossmedia Data Relations really rock, I want to share with you an example I made. I will spread the example over two posts, and this post here is the first one that demonstrates the implementation of a Data Relation. The second post will cover how to access a Data Relation from inside a Crossmedia campaign. But first, let me explain what a Data Relation is.

Crossmedia Data Relations

A Data Relation is a relation between the campaign database, you add to your cross media template, and other table(s) from a different data source. Such a data source can be almost everything you have in mind, for example a third party database or a web service. The data relation is the logic that glues tables from those two data sources together.

A Data Relation is a .Net assembly that comes with a pluggable interface based on the Managed Extensibility Framework (MEF). It has the charming advantage that such an assembly already has everything it needs to be accessible by DSMX. All you need to add is code to communicate with your data source to return data tables back to DSMX (which is pretty easy, as you will see).

What you need to create your own Data Relation

Because a Data Relation is a .Net Framework assembly you need Microsoft Visual Studio to build your sources. A Visual Studio Express is fair enough. It doesn’t matter if your are friend with C# or prefer Visual Basic.NET, you should have basic experiences in one of those .NET languages though. My sample is written in VB.NET by the way.

Data Relations example

Sharpen your tools is important in almost every field and especially in software development. That’s why I have one side project for over ten years now that I continuously rewrite every now and then. The application is a web based DVD management software that keeps track of your movies, if they are in the shelf or borrowed by a friend. Adding new movies is done by typing the title of the movie into a web form. A request is then sent to amazon to get all movie details. Those details are then persisted in a database.

To show you how a DSMX data relation could be implemented I extracted the part that queries Amazon web services. The data relation in other words can do a search for a title against Amazon and return a table that contains detailed information about movies you searched for. If you search for Batman, for instance, Amazon will return certainly a long list of movies.

Implementation. Setting up the project

I will not go to much into detail, because Christoph wrote a very good documentation which you will find pretty straight forward, I promise. It describes thoroughly all methods and properties the interface provides and an top it includes sample code.

Enough talk, let’s start with an empty Class Library project in Visual Studio and call it SearchAmazon. We need the following references to be added to out project:

  • System.ComponentModel.Composition (what is in fact the Extensibility Framework)
  • DataRelationInterfaces.dll ( a component that provides us with the necessary interfaces by DirectSmile)

After that we can remove the class or module that came with the Visual Studio project template a add new class and name it SearchAmazon as well.

Because our class should be exposed to DSMX later on, we must decelerate the class with the Export and the ExportMetaData attribute.

We also want to implement two interfaces called IDataRelation and IDataRelation_LoadTableNameWithParameters.

All that done the body of your class should look like this:

clip_image002

Implementation. Adding logic to your class

First we need a display name for our relation that is shown later in the Data Relations dialog of the DSMX designer.

Public ReadOnly Property DisplayName As String Implements DataRelationInterfaces.IDataRelation.DisplayName
        Get
            Return "Amzon Movie Search"
        End Get
End Property

Then we have to decide what parameters we like to pass from our campaign to the Data Relation:

  • the movie title we search for
  • the Amazon Web Services Developer Id
  • the secret developer for Amazon Web Services
Public Sub GetMetaData(AccountID As Integer, Language As String, MetaData As DataRelationInterfaces.Objects.IhtDataProviderMetaData) Implements DataRelationInterfaces.IDataRelation.GetMetaData
        MetaData.AddParameter("AWSSKeyId", "Amazon Web Services Developer ID", "", True)
        MetaData.AddParameter("AWSSecretKey", "Amazon Web Services Secret Key", "", True)
        MetaData.AddParameter("title", "Movie title", "", False)
End Sub

Later, in the Data Relations dialog, those parameters are exposed by name and description and we can add values to them. The last parameter of the AddParameter method is of interest, if that boolean is set to true a password text field is shown and typed-in characters are hidden.

Next we implement the GetTableNames method. Although this method allows a list of tables, as the method name implies, we just add a single table to the collection, holding our search result.

Public Sub GetTableNames(AccountID As Integer, Language As String, IhtDataProviderTablesList As DataRelationInterfaces.Objects.IhtDataProviderTablesList) Implements DataRelationInterfaces.IDataRelation_LoadTableNamesWithParameters.GetTableNames
        IhtDataProviderTablesList.AddTable("Amazon search result")
End Sub

There a lot more properties we can implement what makes the navigation in our Data Relation much more convenient, like support for column selection, column filtering, order by or paging. But this would extend this little example, but please refer to the documentation if you are interested. I, for the moment, return just false in all those properties, which means it’s not supported.

Public ReadOnly Property supportsColumnSelection As Boolean Implements DataRelationInterfaces.IDataRelation.supportsColumnSelection
        Get
            Return False
        End Get
End Property

Public ReadOnly Property SupportsDistinct As Boolean Implements DataRelationInterfaces.IDataRelation.SupportsDistinct
        Get
            Return False
        End Get
End Property

Public ReadOnly Property SupportsFilter As Boolean Implements DataRelationInterfaces.IDataRelation.SupportsFilter
        Get
            Return False
        End Get
End Property

Public ReadOnly Property SupportsOrderBy As Boolean Implements DataRelationInterfaces.IDataRelation.SupportsOrderBy
        Get
            Return False
        End Get
End Property

Public ReadOnly Property SupportsPaging As Boolean Implements DataRelationInterfaces.IDataRelation.SupportsPaging
        Get
            Return False
        End Get
End Property

Now to the most important method, the LoadData method. As the name implies, the method loads the data into our Data Relation table. The implementation does three things:

  • It validates the parameters passed from the campaign manager
  • It sends a search request to the Amazon web services
  • It adds the appropriate fields to our Data Relations table and fills the table with the search result
Public Sub LoadData(Table As DataRelationInterfaces.Objects.IhtDataTable) Implements DataRelationInterfaces.IDataRelation.LoadData
        Dim title As String = Table.GetParameterValue("title")
        Dim secretdeveloperKey As String = Table.GetParameterValue("AWSSecretKey")
        Dim developerId As String = Table.GetParameterValue("AWSSKeyId")

        if String.IsNullOrEmpty(title)
            Throw New ArgumentException("Movie title parameter must have a value.") 
        End If

        if String.IsNullOrEmpty(developerId)
            Throw New ArgumentException("AWS Developer Id parameter must have a value") 
        End If

        if String.IsNullOrEmpty(secretdeveloperKey)
            Throw New ArgumentException("AWS Secret Key parameter must have a value.") 
        End If

        Dim result As List(Of Movie)
        Dim itmLookUp As New Amazon.ItemLookup(developerId,secretdeveloperKey)

        result = itmLookUp.SearchByTitle(title)

        If result IsNot Nothing Then

            AddFields(Table)

               For Each m In result
                    Addrow(m, Table)
               Next

         End If

 End Sub

 Private Sub AddFields(ByRef table As IhtDataTable)
        table.AddField("ID")
        table.AddField("Name")
        table.AddField("Actor1Name")
        table.AddField("Actor3Name")
        table.AddField("Actor2Name")
        table.AddField("DirectorName")
        table.AddField("EAN")
        table.AddField("ASIN")
        table.AddField("PublishDate")
        table.AddField("Publisher")
        'Todo: Add more fields here ...
End Sub

 Private Sub Addrow(m As Movie, byref table As IhtDataTable)

        Dim r As IhtDataTableRow
        r = table.AddRow
        r.AddValue(table.RowCount + 1) 
        r.AddValue(m.Name)
        r.AddValue(m.Actor1Name)
        r.AddValue(m.Actor3Name)
        r.AddValue(m.Actor2Name)
        r.AddValue(m.DirectorName)
        r.AddValue(m.EAN)
        r.AddValue(m.ASIN)
        r.AddValue(m.PublishDate)
        r.AddValue(m.Publisher)
        'Todo: Add more values here ...
    End Sub

The actual call to Amazon is abstracted into a helper class called ItemLookup. That calls takes our AWS logon credentials in the constructor and provides one simple method called SearchByTitle. That method returns a list of Movie, which is a simple type that contains a set of properties. The names of the properties will become the field names of our table, which are added in the AddFields method. While iterating through the search result the AddRow method takes the Movie type and adds it the row collection of the Data Relation table.Throwing an exception inside a Data Relation is bubbled through the interface and directly visible in the DSMX Designer. The LoadData method takes advantage of this while validating the parameters. Very handy by the way.

Conclusion

With Data Relations we have a powerful tool in hand that offers us new opportunities to merge data from different data sources into our campaign data.

As we will see in the next post, this feature can really play it’s strength in building rich client applications using the Crossmedia Designer. In my opinion, as a software developer, this flexibility must not be underestimated. Software development is in a process of moving from the ivory tower where just a few people were able to aggregate data and build reporting applications, to a point where the architectural plumbing is more and more available or generated automatically and a majority of people can start building applications using those automatically aggregated data. The Crossmedia Designer is an excellent example!