Playing with IE8: Reports Module as a WebSlice

So, I downloaded and installed the IE8 Beta yesterday and decided to play around with WebSlices. I found it really easy to create a simple WebSlice (just apply some CSS Classes) and I decided to try and do this with the Reports Module.

I was suprised with just how easy it was! I have already created a replacement ViewReports.ascx file that turns every Reports Module into a WebSlice. I've attached the new file here, just replace your existing DesktopModules/Reports/ViewReports.ascx file with it if you want to check it out. Any Visualizer should work, but I've only tried the Grid.

CAUTION: This is for preview purposes ONLY! This replacement file has NOT been tested in ANY SIGNIFICANT WAY (other than trying it out once). Back up your existing ViewReports.ascx file BEFORE using this!

Here's the popup you see when you view a report

And here's a screenshot of the WebSlice in action:

Anyway, the file is attached. Try it out on one of your test sites! I'll probably integrate this into an upcoming version in a more configurable way, since it's so easy :).

ViewReports.zip (.54 KB)

UPDATE: Changed to a ZIP file

Developing an RSS Data Source - Part III

In this series of blogs, I'm going to follow the development of an RSS Data Source. I'm going to use Visual Studio 2008, but I'll be using .Net 2.0 features so you should be able to follow along in Visual Studio 2005. You can also use the Express editions of Visual Web Developer (both 2005 and 2008 versions should work). All the code will be in VB.Net, but it should be straightforward enough for C# developers to understand (after all, its all .Net)

Continued from Part II.

Part III - Settings

In this part, we're going to add a setting page so that we can change the RSS feed that our Data Source downloads.

In current versions of the Reports Module, Data Source settings are stored in the ModuleSettings table provided by DotNetNuke. This ensures that all copies of the same module instance will share the same Data Source settings (Visualizer settings are not shared between copies). However, Data Source developers need not (and should not) access these directly. Instead, the Reports Module provides a layer on top of the ModuleSettings table called "Data Source Settings". When the Data Source is executed, the Reports Module passes a Dictionary containing these settings (inside the ReportInfo object). To allow users to edit the settings, we go back to the Settings.ascx file we created in Part I.

Let's start with the user interface for our settings page. All we need for now is a place for the user to enter a feed URL. When we're done, it should look like the screenshot below

The finished settings UI

Figure 1 - The finished settings UI

So, open up the Settings.ascx file and make sure you are in Design mode. First we need to add a label, so users know what they should type in our text box. In the Solution Explorer, find the file: controls/labelcontrol.ascx and drag it on to the design surface.

Locating the LabelControl.ascx file

Figure 2 - Locating the LabelControl.ascx file

Next drag an ASP.Net TextBox control, from the Toolbox, on to the surface. You should have something that looks like this:

Locating the LabelControl.ascx file

Figure 3 - Locating the LabelControl.ascx file

Now, set the properties of the controls to the following values:

Property Value for Label Value for Text Box
ID feedUrlLabel feedUrlTextBox
ControlName feedUrlTextBox N/A
Width N/A 100%

Save your changes, and open up the code file: Settings.ascx.vb. Here, we need to add code to connect our text box to the Data Source settings. The key to this is the LoadSettings and SaveSettings methods provided by ReportsSettingsBase. First, we need to import some extra namespaces:

Imports DotNetNuke.Modules.Reports

Imports System.Collections.Generic

Then, we can implement the LoadSettings and SaveSettings methods.

Public Overrides Sub LoadSettings(ByVal Settings As Dictionary(Of String, String))

    MyBase.LoadSettings(Settings)

    feedUrlTextBox.Text = SettingsUtil.GetDictionarySetting(Settings, _

                                                            "FeedUrl", _

                                                            String.Empty)

End Sub

 

Public Overrides Sub SaveSettings(ByVal Settings As Dictionary(Of String, String))

    MyBase.SaveSettings(Settings)

    Settings("FeedUrl") = feedUrlTextBox.Text

End Sub

The LoadSettings method is provided with a System.Collections.Generic.Dictionary(Of String, String) containing the current settings saved for the Data Source. Our implementation uses the SettingsUtil helper class (provided with the Reports Module) to retrieve a value from the dictionary, or return a default value if it doesn't exist (in this case, an empty string).

The SaveSettings method is also provided with the current settings. However, this method is responsible for retrieving the values entered by the user and updating the settings.

Save the file, and navigate to the Settings page on your test module. You should see our new Settings control displayed, as in the screenshot below:

Settings page so far

Figure 4 - Settings page so far

Oops, we still need to put the label text in! We're going to support the DotNetNuke Localization Framework, so we need to put the text in two places.

First, lets add the localized text. Create a Resource File called Settings.ascx.resx in /DesktopModules/Reports/DataSources/RSS/App_LocalResources file and open it. In Visual Studio, you get a nice table interface for editing resource strings. Add the following entries to the table (feel free to tweak the values as you want, just keep the name the same):

Name Value
feedUrlLabel.Text RSS Feed URL
feedUrlLabel.Help Enter the URL to an RSS feed to retrieve data from

Your resource file should look like this after making those changes

Resource File after entering values

Figure 5 - Resource File after entering values

Now, go back to Settings.ascx and set the following properties on the label we created earlier:

Property Value
Text RSS Feed URL
Suffix :
CssClass SubHead

Note: That's a colon (':') in the Suffix property. Also, CssClass is case sensitive.

Now, save and refresh your page. You should see something like the screen shot below:

Finished Settings UI

Figure 6 - The finished Feed URL text box

Now, to change our Data Source code to use this new setting. Let's go back to the /App_Code/RSSDataSource/RSSDataSource.vb file and take a look at the signature for the ExecuteReport method:

Public Overrides Function ExecuteReport(ByVal report As ReportInfo, _

                                        ByVal hostModule As PortalModuleBase, _

                                        ByVal inputParameters As IDictionary(Of String, Object)) As System.Data.DataView

The important parameter here is the report parameter. There is a property called DataSourceSettings on that object which contains the same dictionary we created in SaveSettings. First, delete the FeedUrl constant we were using before. Then add following code to the beginning of the ExecuteReport method to get the Feed URL from the settings:

If Not report.DataSourceSettings.ContainsKey("FeedUrl") Then

    Throw New RequiredSettingMissingException("FeedUrl", MyBase.ExtensionContext)

End If

Dim feedUrl As Uri = Nothing

If Not Uri.TryCreate(report.DataSourceSettings("FeedUrl"), UriKind.Absolute, feedUrl) Then

    Throw New RequiredSettingMissingException("FeedUrl", MyBase.ExtensionContext)

End If

This code checks for the setting, and if it isn't present or if it isn't a valid URL we throw an exception provided by the Reports Module: RequiredSettingMissingException. We pass it the name of our setting and some contextual information about our Data Source (which is provided automatically by our base class. If the setting isn't present, the Reports Module will automatically display a useful error message indicating that the setting is missing.

While we're in the code, let's add HTML Decoding directly to the Data Source, so we don't have to use the HTML Decode converter in the Module Settings. To do that, we change the line that adds entries to the output table so that it automatically HTML Decodes the description:

dt.Rows.Add(title, New Uri(link), HttpUtility.HtmlDecode(description))

Make sure everything is saved and go back to the website. You should probably go back to the home page, just to make sure everything is properly recompiled. Go back to the settings page for the Reports Module, and make sure the RSS Data Source is selected. Then configure it with your favourite RSS feed. This time, I'll use my personal blog's RSS feed (WARNING: Shameless plug alert!).

Testing the Settings UI

Figure 7 - Testing the Settings UI

Once you've done that, make sure the HTML Decode property is set and the HTML Visualizer is properly configured, just like in part 2 and click Update. You should see the RSS feed displayed just like in Part 2, only now we can change the URL!

Final Results

Figure 8 - The Final Results

Conclusion

At this point, we have a working RSS Data Source! You can stop here if you want, but in the next part I'll cover packaging the Data Source up so that it can be installed in any Reports Module installation.

Download the code so far.

Developing an RSS Data Source - Part III

In this series of blogs, I'm going to follow the development of an RSS Data Source. I'm going to use Visual Studio 2008, but I'll be using .Net 2.0 features so you should be able to follow along in Visual Studio 2005. You can also use the Express editions of Visual Web Developer (both 2005 and 2008 versions should work). All the code will be in VB.Net, but it should be straightforward enough for C# developers to understand (after all, its all .Net)

Continued from Part II.

Part III - Settings

In this part, we're going to add a setting page so that we can change the RSS feed that our Data Source downloads.

In current versions of the Reports Module, Data Source settings are stored in the ModuleSettings table provided by DotNetNuke. This ensures that all copies of the same module instance will share the same Data Source settings (Visualizer settings are not shared between copies). However, Data Source developers need not (and should not) access these directly. Instead, the Reports Module provides a layer on top of the ModuleSettings table called "Data Source Settings". When the Data Source is executed, the Reports Module passes a Dictionary containing these settings (inside the ReportInfo object). To allow users to edit the settings, we go back to the Settings.ascx file we created in Part I.

Let's start with the user interface for our settings page. All we need for now is a place for the user to enter a feed URL. When we're done, it should look like the screenshot below

The finished settings UI

Figure 1 - The finished settings UI

So, open up the Settings.ascx file and make sure you are in Design mode. First we need to add a label, so users know what they should type in our text box. In the Solution Explorer, find the file: controls/labelcontrol.ascx and drag it on to the design surface.

Locating the LabelControl.ascx file

Figure 2 - Locating the LabelControl.ascx file

Next drag an ASP.Net TextBox control, from the Toolbox, on to the surface. You should have something that looks like this:

Locating the LabelControl.ascx file

Figure 3 - Locating the LabelControl.ascx file

Now, set the properties of the controls to the following values:

Property Value for Label Value for Text Box
ID feedUrlLabel feedUrlTextBox
ControlName feedUrlTextBox N/A
Width N/A 100%

Save your changes, and open up the code file: Settings.ascx.vb. Here, we need to add code to connect our text box to the Data Source settings. The key to this is the LoadSettings and SaveSettings methods provided by ReportsSettingsBase. First, we need to import some extra namespaces:

Imports DotNetNuke.Modules.Reports
Imports System.Collections.Generic

Then, we can implement the LoadSettings and SaveSettings methods.

Public Overrides Sub LoadSettings(ByVal Settings As Dictionary(Of String, String))
    MyBase.LoadSettings(Settings)
    feedUrlTextBox.Text = SettingsUtil.GetDictionarySetting(Settings, _
                                                            "FeedUrl", _
                                                            String.Empty)
End Sub

Public Overrides Sub SaveSettings(ByVal Settings As Dictionary(Of String, String))
    MyBase.SaveSettings(Settings)
    Settings("FeedUrl") = feedUrlTextBox.Text
End Sub

The LoadSettings method is provided with a System.Collections.Generic.Dictionary(Of String, String) containing the current settings saved for the Data Source. Our implementation uses the SettingsUtil helper class (provided with the Reports Module) to retrieve a value from the dictionary, or return a default value if it doesn't exist (in this case, an empty string).

The SaveSettings method is also provided with the current settings. However, this method is responsible for retrieving the values entered by the user and updating the settings.

Save the file, and navigate to the Settings page on your test module. You should see our new Settings control displayed, as in the screenshot below:

Settings page so far

Figure 4 - Settings page so far

Oops, we still need to put the label text in! We're going to support the DotNetNuke Localization Framework, so we need to put the text in two places.

First, lets add the localized text. Create a Resource File called Settings.ascx.resx in /DesktopModules/Reports/DataSources/RSS/App_LocalResources file and open it. In Visual Studio, you get a nice table interface for editing resource strings. Add the following entries to the table (feel free to tweak the values as you want, just keep the name the same):

Name Value
feedUrlLabel.Text RSS Feed URL
feedUrlLabel.Help Enter the URL to an RSS feed to retrieve data from

Your resource file should look like this after making those changes

Resource File after entering values

Figure 5 - Resource File after entering values

Now, go back to Settings.ascx and set the following properties on the label we created earlier:

Property Value
Text RSS Feed URL
Suffix :
CssClass SubHead

Note: That's a colon (':') in the Suffix property. Also, CssClass is case sensitive.

Now, save and refresh your page. You should see something like the screen shot below:

Finished Settings UI

Figure 6 - The finished Feed URL text box

Now, to change our Data Source code to use this new setting. Let's go back to the /App_Code/RSSDataSource/RSSDataSource.vb file and take a look at the signature for the ExecuteReport method:

Public Overrides Function ExecuteReport(ByVal report As ReportInfo, _
                                        ByVal hostModule As PortalModuleBase, _
                                        ByVal inputParameters As IDictionary(Of String, Object)) As System.Data.DataView

The important parameter here is the report parameter. There is a property called DataSourceSettings on that object which contains the same dictionary we created in SaveSettings. First, delete the FeedUrl constant we were using before. Then add following code to the beginning of the ExecuteReport method to get the Feed URL from the settings:

If Not report.DataSourceSettings.ContainsKey("FeedUrl") Then
    Throw New RequiredSettingMissingException("FeedUrl", MyBase.ExtensionContext)
End If

Dim feedUrl As Uri = Nothing

If Not Uri.TryCreate(report.DataSourceSettings("FeedUrl"), UriKind.Absolute, feedUrl) Then
    Throw New RequiredSettingMissingException("FeedUrl", MyBase.ExtensionContext)
End If

This code checks for the setting, and if it isn't present or if it isn't a valid URL we throw an exception provided by the Reports Module: RequiredSettingMissingException. We pass it the name of our setting and some contextual information about our Data Source (which is provided automatically by our base class. If the setting isn't present, the Reports Module will automatically display a useful error message indicating that the setting is missing.

While we're in the code, let's add HTML Decoding directly to the Data Source, so we don't have to use the HTML Decode converter in the Module Settings. To do that, we change the line that adds entries to the output table so that it automatically HTML Decodes the description:

dt.Rows.Add(title, New Uri(link), HttpUtility.HtmlDecode(description))

Make sure everything is saved and go back to the website. You should probably go back to the home page, just to make sure everything is properly recompiled. Go back to the settings page for the Reports Module, and make sure the RSS Data Source is selected. Then configure it with your favourite RSS feed. This time, I'll use my personal blog's RSS feed (WARNING: Shameless plug alert!).

Testing the Settings UI

Figure 7 - Testing the Settings UI

Once you've done that, make sure the HTML Decode property is set and the HTML Visualizer is properly configured, just like in part 2 and click Update. You should see the RSS feed displayed just like in Part 2, only now we can change the URL!

Final Results

Figure 8 - The Final Results

Conclusion

At this point, we have a working RSS Data Source! You can stop here if you want, but in the next part I'll cover packaging the Data Source up so that it can be installed in any Reports Module installation.

Download the code so far.