New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

Learning Razor 1 - RSS-App Part 2: Create App and allow Configuration

This is part two of my mini-series Learning Razor Part 1 - Create an RSS-App. In this second part we'll improve it's functionality and security and thereby remove most of its previous shortcomings. After this post, normal admin users can add the App to any page and specify the feed-url without your help.

What we'll Add In Part 2

The basic Razor-Host will parse CSHTML for you, but this is usually just not enough. We want to add the following functionality now:

  1. Extract the configuration out of the script - so we'll put the feed-url somewhere for the normal Admin to configure
  2. Allow separate configuration for each…
    1. …instance of the script (so different pages show different feeds)
    2. …language of the script (because often the DE-Feed should be different than the EN-Feed)
  3. Add some CSS
  4. Take it out of the /DesktopModules/
    1. To improve security (so that the script isn't shared)
    2. Allow Portal specific customization
    3. Add more resources (like CSS-Files) again portal-specific
  5. Package it all for easy re-distribution

These things are not possible with the default Razor-Host, so we need a turbo-charged Razor Host, mixed in with some Form-And-List features and more. About 2 years ago we took the razor host and enhanced it with all these features and created 2sxc (can be found in the forge, on codeplex, github and with documentation). For the next steps, we'll use this - since it's super-easy. Of course you could also create your own modules to do this - but for the tutorial it's best to stick to this version.

Preparation: Install Everything

Since we're here to learn Razor, it's best to simply install the finished solution first, and then discover it's elements within the running, working solution. You will need:

  1. 2sxc 6.2 or higher - get it from the forge or directly from Codeplex
  2. The App itself - available on the forge and codeplex (note: this is the V2 App, for the next blog I'll post a V3 App...)

These are trivial steps but would take many pictures to explain, so I quickly made a video:

Understanding the Enhanced Razor Host in 2sxc

The following information are not Razor-specific, but helpful to understand what this new Razor-Host does for you - since you'll be using some of the features. Here's what you need to know:

  1. File storage has moved from the /DesktopModules/ to the [Portalfolder]/2sxc/Razor-Tutorial-RSS V2/
    1. You can also add CSS-files (I added it into the subfolder /assets/) and anything else like JavaScripts etc.
    2. This allows us to have an own App for each portal - so enhancements to this App (like changes in the design) won't break another portal.
    3. You could actually also install the same App again in another folder - for example if you've modified the original App a lot (and want to keep your changes), but want to install a newer, different RSS-App again.
    4. Any changes in this folder will also be included if you re-export the App later on for re-distribution
  2. It's now an App, not a DNN-Module, so adding it to a page requires you to add the "App" module and then select our Razor-Tutorial RSS-Demo V2 app.
  3. The Razor-Host can optionally use the 2sxc-built-in Data Storage to save any kind of data like content and configuration; and will automatically deliver it to the Razor-Script when needed.

In the following Video I'll quickly walk you through this - also how the data-storage is configured. This is not programming but presents an important basis on which we will program. Again: you could do all this with your own modules as well (manage settings, resources, multiple templates etc.) but in the 2sxc Razor Host it's all there for free:


Using What the User Enters

This was the initial code where the configuration values were in the CSHTML:

And here is the new code

...and the same code, shrunk a bit since we don't need all that

 You'll see that only very little changed in this step. We just replaced the static values with Content.*.

Where did that Content come from?

You're probably wondering where the Content variable came from, so here's a short explanation: Every day we learn that a good MVC-pattern is the way to go. In 2sxc, the model would be your Content variable (+ some others), and 2sxc itself is the controller. It ensures that the model/data is prepared before the template starts and that it contains everything you need. So this new powerful Razor Host takes care of most of the M and the C, so you can focus on your V - your Razor-View.

The Content-variable is a Dynamic-Object. So if you add more fields in the configuration, you can automatically use them in your code. This is why you can write @Content.Title or @Content.NumberOfItemsToShow.

Naming: Content, ViewBag, ViewData or ViewModel?

Most Razor-Samples you'll find use either a ViewBag["name"] and also, a ViewData["name"] or a in the code samples. This is because the MVC controller loads the View and attaches these variables to the Razor object to work with. We found that this is rather confusing - especially to beginning developers who just want to create a simple responsive view of some user entered content. Because of this, the 2sxc Razor Host attaches a lot more variables with specific purposes. Content is the most important, but you'll also find Data, App and many more for advanced functionality. 

At the moment, there is no convention in DNN what these variables should be called - and there may be a recommendation in the future, but I believe that each module will have to decide on it's own. If you create your own host, please use something that's easy to understand. In 2sxc it's usually Content (the stuff the editor added to this module), Data (data added by the data-pipeline, like additional categories) and App.Data (the entire data-pool of this App).

Try a bit yourself…

Go ahead and mess about with the code. You can do it in Visual Studio or with the edit-template functionality. And don't worry: you can always uninstall the App and install it again when you break it :).

Wrapping up Phase 2 - Good and Bad

So now we have a much improved Razor-based App.

A lot of the shortcomings are fixed

  1. It needs a programmer to change the feed-url because it's stored in the CSHTML… > fixed
  2. …and because it's Razor, you also need Host-permissions. Not sexy :( > fixed
  3. The script lies in /DesktopModules/ - so it's shared across portals. This isn't nice for security reasons, and also not because you might want different looks on each portal. > fixed
  4. You can't really package your work and re-distribute it. > fixed
  5. You can't have instance-based settings. So every time you had a feed, you would need to create a new script - which you would have to maintain in the future. > fixed

...And has these shortcomings Left

  1. It's not multi-language capable - so if you needed a different feed in another language, again you would have to create a new script - or additional fields for each language
  2. It doesn't show images and doesn't look good yet (because of missing CSS)
  3. It's not integrated in the DNN-Search yet
  4. The admin can't control the presentation (like decide to show/hide images or reduce the amount of items)
  5. The admin couldn't easily switch to another view like a 2-column look instead of a table
  6. No cool animations like light-boxes
  7. The in-html placeholders still look pretty ugly
  8. No image support on the RSS-feed

All these shortcomings will be handled in the following lessons :). Stay tuned!

With love from Switzerland

Daniel Mettler grew up in the jungles of Indonesia and is founder and CEO of 2sic internet solutions in Switzerland and Liechtenstein, an 20-head web specialist with over 600 DNN projects since 1999. He is also chief architect of 2sxc (2SexyContent - see forge), an open source module for creating attractive content and DNN Apps.

Thanks very much for your share. I just post a 5 stat view on (my account on codeplex is xiaoqi98).

I met a few issue while test the, as follows:
1. When install on DNN 7.3.0, and try load the default templates, it shows below error:
"Something went wrong while installing 'QR Code': Internal Server Error - Could not import the app: Could not load file or assembly 'SharpZipLib, Version=, Culture=neutral, PublicKeyToken=null' or one of its dependencies"
The error, is because DNN 7.3.0 introduces a new version of "SharpZipLib.dll", In DNN 7.3.0, it uses ICSharpCode.SharpZipLib.dll, not "SharpZipLib.dll".
However, DNN rollback to "SharpZipLib.dll" after 7.3.0. So it issue only occurs in DNN 7.3.0.

2. It seems module works only for {databaseOwner} = dbo, and {objectQualifier} is empty. When install module on a DNN instance which has objectQualifier specified (e.g, dnn), it will throw a error and failed to install.

Anyway, it is still a great module and it is worth to spend time to study. Thanks. Monday, December 8, 2014 5:04 AM (link)
Daniel Mettler
thanks for the great rating :)
Yes, it only works with the default object qualifier, because we're using Entity Framework.
Daniel Mettler Monday, December 8, 2014 10:10 AM (link)

Comment Form

Only registered users may post comments.


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Daniels (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Steven Fisher (1)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out