About Us

Why DotNetNukeBlogs.com? Our goal is to be the premier aggregator of DotNetNuke related materials. DotNetNukeBlogs.com was started by DotNetNuke Core Team member employee community member Chris Hammond with the intention to provide a place for the leaders in the DotNetNuke Community to push their content to those needing it most, the users.

If you're a DotNetNuke Expert be sure to get your feed added into our aggregate system. You can read more about us here

DotNetNuke Hosting

Hosting for this website is provided by AppliedI.Net. Be sure to visit them for all your DotNetNuke Hosting needs. 

Latest Community DotNetNuke Blog Posts

DNN Connect
Thursday, August 28, 2014 4:00:00 AM
Along came MVC to provide a new solution. And there are quite a few things it's done very, very well. And a lot of things that won't make it. Our goal is to focus our time and energy on the relevant parts and ignore the rest. In this part 4 of my Series The Future of DNN Speaks Razor, I'll explain why ASP.net MVC started well but was overtaken by the internet, and why the resulting good solution is still called MVC, even though it's not Model-View-Controller.
The Mighty Blog
Wednesday, August 27, 2014 9:28:43 PM

Google Hangouts

If you’re not sure what a Google Hangout is, well…  You’ve been under a rock for a while.  Simply put, this is a very easy and web-based way to talk to someone face-to-face, from any nearly web-based device that has a web browser.  You can do this one-on-one like with Skype, or you can use this for more of a public webinar kind of use case.  It’s part of the whole Google+ suite of features.  Even if you’re not actively using Google+, this feature is pretty sweet.  It’s amazing what they’re able to enable you to do with a web browser!  If you’re doing the latter, you might want to read on…

It’s been a long while since I’ve released a NEW module into the DNN community – maybe at least a year ago since my last release.  It’s been even longer since I’ve blogged here, and I am sorry for that.  But as I said on twitter the other night, I’m back! I’ve had some modules go out into the wild that you might not have heard of, including a couple for user groups as proof of concepts, and even an update to the Media Module in February.  (Do a search for “user group labs” for the others on codeplex.)

Google Hangout for DNN

If you’re reading this and not using DNN, sorry.  But this is an open source module, so if you’re a developer, you can take a look at the source for this module (and many of my others) on github.  You’ll be able to see this module in action next week though for a live DNN webinar with

Peter Donker (T|B|L), Joe Brinkman (T|B|L), and myself.  You can follow our twitter feeds to get those details as soon as they’re available.

“Hey Will.  Why should I build a module for this?  Google Hangouts has an embed code.  I can just copy and paste it.”

If you are asking yourself that, you’re absolutely right, and there’s nothing to prevent you from doing that.  However, having a module to manage this gives you the benefit of structured content, ability to delegate management of Hangouts to non-technical people, and there are more features and purposes planned for this module that will be announced later.

DNN Hangout Features

This is a first release, so there is going to of course be a minimal number of features, and they include:

  • Quickly add a Google Hangout via copy/paste
  • Template available to change how the module is displayed to users
  • Show start date/time and duration for future/past Hangouts

For those of you that are developers, here is a feature list for you!

  • Uses content items for the DAL
  • Uses DNN token replace
  • Uses PortalSecurity for user input filtering

This version 01.00.00 release has the following minimum requirements.

  • DNN version 07.02.00 or newer
  • SQL Server 2005 or newer
  • Microsoft.Net version 4.0 or newer

How do I use DNN hangout? 

Today, the features are simple…  You create a hangout in Google Hangout.  It can be a regular hangout, but what this module is really meant for is On Air Hangouts.  These are the kind of hangouts where you would be broadcasting an even to the public. 

Next, you copy the hangout URL, video ID, or embed code.  This module will accept them all and magically grab the information it needs from you.  Go into the module’s edit view to manage those settings.

Choose to edit the DNN Hangout Module

Once you see the edit view, add the relevant information, including the Google Hangout information you copied earlier.

Edit the DNN Hangout Module settings

You even have some sample Google Hangout addresses to test and compare with to make sure you’re adding the right information.  As long as you add the right address, it will be parsed and the video ID will be the only thing that remains once you save.

DNN Hangout module settings (bottom half)

Now that you have the right information in place, you can save your new hangout and you’ll see it immediately on the page.

Google Hangout with default template in DNN

This is probably not how you want your hangout to be displayed on you site.  Don’t worry…  You’re covered with the module settings.  Just update the default template with your own HTML and use the placeholder tokens to add the hangout information in the places of the HTML that you want.  Once you save it, your changes will be reflected on the page.  You should know that this module also supports DNN tokens, so feel free to add things like user personalization if you want.

DNN Hangout module settings - template

DNN Hangout Downloads

If you want to try out the DNN Hangout Module, all you have to do is download it and install it like any other module.  You’ll find a link below.

Download DNN Hangout

PowerDNN Blog
Wednesday, August 27, 2014 6:31:01 PM
We weren’t bought; We’re growing Here at PowerDNN, we’ve been dedicated to providing the best possible service and support for DNN / DotNetNuke. Our company was built on DNN, providing a great product at a competitive price, and — most of all — our deep commitment to our customers and the Community. Many companies preach […]
DNN Connect
Wednesday, August 27, 2014 12:00:00 AM
As you might have heard, you have to migrate to Razor soon. Old-school developers have a hard time understanding why WebForms should be replaced, since it's worked to well for more than 10 years. So in this part 3 of my Series The Future of DNN Speaks Razor, I'll explain why WebForms turned out to be the wrong solution for web development and how the web changed to make WebForms' strengths obsolete.
DNN Connect
Tuesday, August 26, 2014 11:56:00 AM
As you might have heard, you have to migrate to Razor sooner than later, and the earlier you start, the more you will be creating future-compatible material today. This is part 2 of the Series The Future of DNN Speaks Razor. In this post I'll explain what Razor is, why it's not MVC (even though Razor is popular there as well) and more.
DNN Connect
Monday, August 25, 2014 11:26:00 AM
If you're an old-school DNN developer you're used to using ASP.net Forms - and you've developed tricks and techniques to compensate for various issues like clean SEO-HTML, JavaScript-Control-IDs and more. Things have changed - but most DNN-dudes don't realize this yet. Because the future is in absolute HTML control - using Razor. Let me tell you why, and how to get started.  This is part 1 of the Series The Future of DNN Speaks Razor. In this post I'll explain why you have to migrate now.
DNN Connect
Wednesday, August 20, 2014 7:55:00 PM
I my opinion, the DNN community thinking is on a turning point. DNN Community involvement in the development of the platform, discussion about it, defining strategy, was less and less over the past 2-3 years. However, the DNNPlatform as such, the software itself, has improved a lot over these past years, new functionality, broader set of features, professional build process, more professional issue handling, etc.
DNN Connect
Tuesday, August 19, 2014 3:56:00 AM
August 13th, 2014. I woke up in an alternate reality this morning. The reality where Shaun Walker was no longer with DNN Corp. It must have been all of 5 minutes between his resignation being made public and a message popping up on my iPad as I was preparing to go to bed. "It happened", it read. "It" being something the sender and I had discussed earlier as something that might happen in the near future. The third founder to leave the Corp and without doubt the most famous of all of them. And within an hour the interwebs were firing up with discussions about what this would mean for "us". Us, the DNN community that is. What do we make of this? At times like these I feel like we're Kremlin watchers. "Hey, so-and-so's now on the left instead of the right of the supreme leader at the parade. Did he get demoted?" So Shaun signs out with a short goodbye. And Joe posts a somewhat more elaborate post on how he intends to fill his shoes (Joe is now the o ...
DNN Connect
Wednesday, August 13, 2014 5:07:00 AM
I used to believe QR codes were useless marketing gimmicks. Then I visited Japan in 2011 and QR codes were everywhere. You could see them on the walls of skyscrapers in Tokyo, on product packaging - and even on every tiny 1x3-inch ads in the magazines. Usually it's time to re-evaluate an opinion once you see that an large, smart group of people have an opposing point of view. So I re-evaluated. In this blog I would like to tell you what the QR-Code is (in case you're new to it), why it's great, and how to make bad and good QR-codes (as it's easy to botch up).
Tricky Coder
Saturday, July 26, 2014 4:16:00 AM

Introduction & Background

I have experience working on an existing dnn site that has lots of custom features and I join the team to contribute as developer, lead or code reviewer. Many times during last 8 years of such experience, I found lots of people are creating role base pages in dotnetnuke and implement some custom login in either login module or somewhere else that can check the role and redirect.

Is this really required?

Example Scenario

Lets say you are working on a hospital portal in dotnetnuke and want to prepare a dashboard for care taker, admin, manager, and bunch of other roles. 

If you create different pages and drop a single module for role wise dashboard, and use some custom logic to redirect user after login to that page, that is something that needs a second though.

Dotnetnuke security inherited from portal > Tab > Module. Inheriting up to module level is recommended for most of the cases.

I would create a page(tab) and drop all the modules that I prepared for role wise dashboards. I would do multiple modules to make things separate and clean but drop all modules to the same page. In module settings of each module, uncheck the inherit permission button and check the role which is expected to see this module. 

Now, without having too much of coding/customization and tricks, each role can easily access data that is expected to their roles. Easy!

What do you think?



DNN Connect
Tuesday, July 15, 2014 8:16:00 AM
I'm happy to announce we have found a location for next year's DNN Connect conference! The world's most convivial DNN event is returning to France. But instead of the bustling capital, we'll gather in the countryside in the town of Millau (world famous for the highest viaduct in the world). And just like last year we'll be introduced to the local flavours and ambience during our event, so get set for some of the local food and wine. These will be hand picked by our local team, the kind folks of Nevoweb. You know, the NBStore guys (and girls). They have booked the Domaine Saint Estève for us from the 28th to the 31st of May (the event itself being on the 29th and 30th). It's a luxurious resort in the heart of one of France's most beautiful natural regions (Parc des Grand-Causses/Cevennes national park).
DNN Connect
Monday, July 14, 2014 6:00:00 AM
As you probably already know, I love no-server-code Apps. They allow admins/web designers to extend their DNN without requiring host-permissions and without risking the system stability. It also allows them to modify the extension with very basic capabilities. When creating the ImageCompare App I ran into some common issues that you will have as well - and would like to share the lessons-learned here.
DNN Connect
Thursday, July 10, 2014 10:10:39 AM
This Blog is about 2 things. On one hand it's about Syntax-Highlighting, but actually it's more about creating safe No-Server-Code-Apps.
DNN Connect
Monday, June 30, 2014 4:36:25 PM
This is something of a pet peeve for me. And whenever I get myself involved in an open source project in DNN, it is one of the first things I’d tackle. The issue I’m referring to, here, is how to properly code settings that are serialized to storage (SQL). So settings are commonly retrieved as a hashtable or dictionary of key/value pairs that are both of a string type. These lists get stored in SQL typically in tables with the “Settings” suffix. I.e. ModuleSettings, PortalSettings, TabModuleSettings, etc. And often modules implement their own settings table because the framework hard wires ModuleSettings to … modules. So if you need portal-scoped settings for your module, you’ll need to create your own table. The old blog module (pre version 6) used to do this, for instance.
Peter Donker
Monday, June 30, 2014 4:33:47 PM

This is something of a pet peeve for me. And whenever I get myself involved in an open source project in DNN, it is one of the first things I’d tackle. The issue I’m referring to, here, is how to properly code settings that are serialized to storage (SQL). So settings are commonly retrieved as a hashtable or dictionary of key/value pairs that are both of a string type. These lists get stored in SQL typically in tables with the “Settings” suffix. I.e. ModuleSettings, PortalSettings, TabModuleSettings, etc. And often modules implement their own settings table because the framework hard wires ModuleSettings to … modules. So if you need portal-scoped settings for your module, you’ll need to create your own table. The old blog module (pre version 6) used to do this, for instance.

So, to begin with the worst of scenarios, let’s look at the version 3 code of the blog module. Here is a snippet from BlogList.ascx.vb:

    BlogSettings = Utility.GetBlogModuleSettings(Me.PortalId, TabId)
    If CType(BlogSettings("PageBlogs"), String) <> "" Then
     m_PersonalBlogID = CType(BlogSettings("PageBlogs"), Integer)
    Else
     m_PersonalBlogID = -1
    End If

The BlogSettings here is a hashtable that has been read from the database. It’s easy to see what is happening, here. First we retrieve the settings hashtable. Then we check if the value for the key “PageBlogs” is an empty string. Note that here is already a first mistake as this will throw an error if the key is not present. Then, if there is a string value there, it is parsed as an integer. Again, this would bomb if the string was not an integer, but this I’ll waive as only the module is setting this value. But it’s not pretty. Finally, if no value was found in the string the value is initialized to –1.

Now you’d look at this and go “yikes”, right? I hope so. Not only do we have several points of failure, we are also managing the settings very close to the UI layer. I.e. we are working to convert from and to settings values right in the codebehind of the ascx, whereas this should ideally be concentrated in the business layer. Not convinced? What if I told you this code reappears in Archive.ascx.vb, Blog.ascx.vb, ModuleOptions.ascx.vb, Search.ascx.vb and ViewBlog.ascx.vb. Messy enough for you? Indeed it’s unbelievable.

Strong typing means we create a wrapper around all this junk and all other code can refer to Settings.PageBlogs which happens to be an integer. So the first step is to create a separate class to hold your settings. For this example I’ll assume we’re doing a “simple” module which stores its settings in ModuleSettings. As you may know these module settings are actually propagated to the UI layer through the Settings property on the PortalModuleBase class that most of your controls inherit from. Again, this is a hashtable. And our goal will be to wrap this up as neatly as we possibly can so we don’t leak any settings management to other parts of our code.

Step 1: Create your settings class

Namespace Common
 Public Class ModuleSettings

#Region " Properties "
  Private Property ModuleId As Integer = -1
  Private Property Settings As Hashtable
  Public Property ShowProjects As Boolean = True
#End Region

What I’ve done is to add 3 properties to this class. The first two are internal properties that I’ll use to manage the settings. The latter (ShowProjects) is my first public setting that I need in my code. Note I’m already initializing the value of that setting. This is important as we’ll see later on.

Step 2: Create the constructor to deserialize the hashtable

  Public Sub New(ByVal ModuleId As Integer)
   _ModuleId = ModuleId
   _Settings = (New DotNetNuke.Entities.Modules.ModuleController).GetModuleSettings(ModuleId)
   ShowProjects = _Settings.GetValue(Of Boolean)("ShowProjects", ShowProjects)
  End Sub

Here we store the module id (which we need later if we want to save settings again) and we retrieve the hashtable, first. Then we try to get the value out of the hashtable to our setting. Note DNN now includes an extension method to simplify this process called GetValue. It does all of what the code did we saw earlier in the example from the blog module, but more efficiently. We now have one line and it will not throw an error if the value is not there and just use the default value if that is so (this is why we need to initialize our properties when we declare them). In fact, I’ve been nagging the core architects to have these methods available for us all so I didn’t need to code similar logic myself all the time.

Step 3: Add caching

For this we’ll use a static constructor as follows:

  Public Shared Function GetModuleSettings(ByVal ModuleId As Integer) As ModuleSettings
   Dim modSettings As ModuleSettings = Nothing
   Try
    modSettings = CType(DotNetNuke.Common.Utilities.DataCache.GetCache(CacheKey(ModuleId)), ModuleSettings)
   Catch
   End Try
   If modSettings Is Nothing Then
    modSettings = New ModuleSettings(ModuleId)
    DotNetNuke.Common.Utilities.DataCache.SetCache(CacheKey(ModuleId), modSettings)
   End If
   Return modSettings
  End Function

  Private Shared Function CacheKey(ByVal ModuleId As Integer) As String
   Return "ModuleSettings" & ModuleId.ToString
  End Function

Here we see how we can make sure we try to cache the complete settings object in DNN’s cache. Note, we let DNN take care of the caching time/expiration/etc.

Step 4: Saving the settings

  Public Sub Save()
   Dim objModules As New DotNetNuke.Entities.Modules.ModuleController
   objModules.UpdateModuleSetting(_ModuleId, "ShowProjects", Me.ShowProjects.ToString)
   DotNetNuke.Common.Utilities.DataCache.SetCache(CacheKey(_ModuleId), Me)
  End Sub

Saving becomes trivially easy as we have all the necessary bits and pieces in place. Note we are no longer doing the settings management for this in the codebehind of the edit control that is shown to the user when editing the settings. All is done within the settings class.

Step 5: Add to your base class

Of course you are using your own class that inherits from PortalModuleBase, right? No? Then you should. And here’s why:

  Private _settings As ModuleSettings
  Public Shadows Property Settings As ModuleSettings
   Get
    If _settings Is Nothing Then
     _settings = ModuleSettings.GetModuleSettings(ModuleId)
    End If
    Return _settings
   End Get
   Set(value As ModuleSettings)
    _settings = value
   End Set
  End Property

What happens here is that the Settings in the good old PortalModuleBase are now being replaced by our own settings class. So now, in your UI code you’ll just use Settings.ShowProjects to access our setting.

Shouldn’t we also do this in the core?

You can probably guess my answer. Yes, we should. You didn’t know that the core is still rife with the code I’ve been lamenting above? Check out the latest source version (7.3.1 as of this writing) and head over to UserController.cs lines 256 and below. You’ll notice blocks like these:

            if (settings["Profile_DisplayVisibility"] == null)
            {
                settings["Profile_DisplayVisibility"] = true;
            }

Here the settings dictionary is being primed to catch errors in case no value is there. Oh dear. That means that the conversions are done at the end point in code. And if we search for the specific string we’ll find it in lines 59-66 of Profile.ascx.cs:

        protected bool ShowVisibility
        {
            get
            {
                object setting = GetSetting(PortalId, "Profile_DisplayVisibility");
                return Convert.ToBoolean(setting) && IsUser;
            }
        }

As we can see we have the string Profile_DisplayVisibility appearing three times. And if they need this setting more often, this string would keep on appearing. The repetition of this string has two major drawbacks: (1) it increases the likelihood of a coding errors by those working on the core code (if you’d misspell Profile_DisplayVisibility you won’t get the setting) and (2) it makes it more difficult for people like myself that work just with the API of the core to determine which settings there are, what type they are and what they’re called. This begs for refactoring. And I sincerely hope this post will make it clear what it is I’m after. I’ve gone ahead and coded a start for this bit of the framework. So if you examine the UserSettings they consist of a set of “sections” (Profile, Security, etc). This can easily be done in a very elegant way as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Controllers;
using DotNetNuke.Entities.Portals;

namespace DotNetNuke.Entities.Users
{
    class UserSettings
    {
        public const string CacheKey = "UserSettingsPortal{0}";

        #region Public Properties
        private int PortalId { get; set; }
        private string CultureCode { get; set; }
        public ProfileSettings Profile { get; set; }

        #endregion

        public static UserSettings GetUserSettings(int portalId, string cultureCode)
        {
            string cacheKey = string.Format(CacheKey, portalId);
            return CBO.GetCachedObject(new CacheItemArgs(cacheKey, DataCache.PortalSettingsCacheTimeOut, DataCache.PortalSettingsCachePriority, portalId, cultureCode), GetUserSettingsCallback, true);
        }
        private static object GetUserSettingsCallback(CacheItemArgs cacheItemArgs)
        {
            var portalId = (int)cacheItemArgs.ParamList[0];
            var cultureCode = (string)cacheItemArgs.ParamList[1];
            Dictionary settingsDictionary = (portalId == Null.NullInteger)
                                                ? HostController.Instance.GetSettingsDictionary()
                                                : PortalController.GetPortalSettingsDictionary(PortalController.GetEffectivePortalId(portalId));
            UserSettings res = new UserSettings();
            res.Profile = new ProfileSettings(settingsDictionary);
            return res;
        }

        public void Save()
        {
            PortalController.UpdatePortalSetting(PortalId, "Profile_DefaultVisibility", Profile.DefaultVisibility.ToString(), false, CultureCode);
            PortalController.UpdatePortalSetting(PortalId, "Profile_DisplayVisibility", Profile.DisplayVisibility.ToString(), true, CultureCode);
        }


        class ProfileSettings
        {
            #region Public Properties
            public int DefaultVisibility { get; set; }
            public bool DisplayVisibility { get; set; }
            #endregion

            public ProfileSettings(Dictionary settingsDictionary)
            {
                DefaultVisibility = settingsDictionary.GetValue("Profile_DefaultVisibility", DefaultVisibility);
                DisplayVisibility = settingsDictionary.GetValue("Profile_DisplayVisibility", DisplayVisibility);
            }
        }

    }
}
This implements the four first steps listed above and as a bonus stacks the settings so you could use UserSettings.GetUserSettings(portalId, cultureCode).Profile.DefaultVisiblity. Now that would be a lot clearer. And here’s another good reason to take the time to do this: we can document these properties. Making the framework even more insanely easy to work with.
More ...
Tags: Development
Ultimate DNN Modules
Friday, June 27, 2014 9:54:53 AM
As we promised ever, we always maintain the independent branch of SunBlogNuke compatible well with older version of DNN  CMS, such as the DNN4-building. Today we would like to announce that we have built another compatible package of SunBlogNuke for DNN5.2+. Even through you are still using the DotNetNuke 5, you don’t have to be worry about it and just feel free to let it there without any update as you like. Surely, the development status is still active; we will include updates with fixes if necessary. You can get it here. We hope that with this generation dnn blog module  you can enjoy the blog writing and it will make your life better; plus if you have any good advice about our products, please feel free to leave a comment or contact us. Note: 1) If your dnn website is DNN5.2 above, you should ignore this package and get more latest package. 2) We may need a quote for premium support for those compatible buildings and our cost will be $25/hour. ----------------------------------------- ...
Engage
Thursday, June 26, 2014 12:07:00 PM

At Engage we believe in investing in the professional development of our employees. While building professionals who can effectively communicate with our customers has always been a priority for us, we also stress a healthy work-life balance.

Recently, I revisited one of the most influential books I've read - The 7 Habits of Highly Effective People. I've read (or listened to) the book four times now throughout my life. Not only does it teach us how to be more "effective" but also reinforces work-life balance principles. I highly recommend it to everyone - especially those who are members of a team.

Realizing how powerful the material is, we've decided to weave The Habits into the Engage culture. This started with an overview/kick-off session where we all took the 7 Habits personal assessment. Based on how we scored, we will all teach one of the 7 Habits to the group - one Habit at a time. While I look forward to a continued deeper understanding of the material (internalizing the habits), most of all I look forward to seeing how our outstanding young professionals can become even more effective in their lives. Our journey awaits, Habit 1: Be Proactive coming next week to Engage...


More ...
DNN Connect
Wednesday, June 25, 2014 9:27:00 AM
This is part of a blog post series accounting for user management in DNN using the User account modules from DNN-Connect, all available as open source extensions on Github.com. Currently we have three different modules available, one for letting people register on the site, one for letting folks update their account details and one for managing user accounts from ad administrative perspective.
ChrisHammond.com
Monday, June 16, 2014 11:19:23 AM
If you’ve recently upgraded to DotNetNuke 7.3, you might not have noticed that your scheduled tasks aren’t running. How do you know if your tasks are running or not? Follow these steps
Engage
Monday, June 16, 2014 3:00:00 AM

What is the latest version of DotNetNuke? Well for starters, these days the DotNetNuke moniker has been dropped by DNN Software. Now it's just DNN. The most current version is DNN 7.3 and it was released on June 11, 2014

RSS URL

Resources

DotNetNuke.com The DNN mothership.

Built by

This site is built and managed by Christoc.com Software Solutions, a leading .NET open source consulting company.