Saturday, June 29, 2013

DotNetNuke & GoDaddy - How to have nice urls

The Problem

For Week 3 I have been working on setting up DotNetNuke.  I have a Windows shared hosting which isn't so bad but it does have it's quirks.  For instance, it loves to add the directory name into the url.

The common wisdom is to place DotNetNuke in the root of the site but that didn't work for my purposes. (Actually I will end up doing that only because I want to make the site currently in the root in DNN). Keeping DNN in it's own virtual directory has presented itself with some challenges.  Obviously I don't want users to see the /dotnetnuke in the url nor do I want it to be required. After a couple days of trial and error I came up with a solution.

The Solution

Step 1:

Assuming you have a working DNN install, set up a Portal Alias for urls with both the virtual directory and non-virtual directory.

Step 2:

Experience with MVC sites says that we can edit the web.config file in order to add rewrite rules.  In order to do this you must be running in IIS integrated pipeline mode.

Since it seems that the root directory tries to handle url rewrites first (GoDaddy thing?), we must add the following code to the system.webServer section of our web.config in the ROOT of the hosting account.

 <clear />
       <rule name="Remove Virtual Directory">
          <match url=".*" />
          <action type="Rewrite" url="{R:0}" />
        <rule name="Rewrite DotNetNuke to Root" stopProcessing="true" enabled="true">
           <match url="^dotnetnuke$|^dotnetnuke/(.*)$" />
           <action type="Redirect" url="{R:1}" redirectType="Permanent" />
        <rule name="Rewrite Root to DotNetNuke " stopProcessing="true" enabled="true">
           <match url="^(.*)$" />
           <conditions logicalGrouping="MatchAll">
  <add input="{HTTP_HOST}" negate="false" pattern=".+\.oneweekonewebsite\.com$" />
  <add input="{PATH_INFO}" negate="true" pattern="^/dotnetnuke$|^/dotnetnuke/(.*)$" />
           <action type="Rewrite" url="dotnetnuke/{R:1}" />

Rule Descriptions:
  1. Rewrite the url to itself.  This is interesting in that it creates an X_ORIGINAL_URL server variable which MVC uses to populate it's routes. This will get rid of the virtual directory on a normal MVC site.
  2. Look for the virtual directory name and redirect to the url without it.  This will get the user's browser to display our nice url if they come from one that includes the virtual directory.
  3. Rewrite a url without the virtual directory to one with the virtual directory. The rewritten url is only used internally by the server so the user won't see this. This will make it so the server matches the request to a request to dnn.  Notice how I added a condition for my domain.  I have multiple domains but is the only one running DNN and I don't want the others to be picked up by it. The regular expression will send any subdomains to DNN.  The second condition will also prevent any urls already containing the virtual directory name from having it added again.
Update: In order for everything to work, your domain should point to the root of the hosing account NOT the virtual directory.

Step 3:

???  I really thought this was more complicated than it is with all the time I spent on this.  Hopefully I can save others some time.  I guess step 3 is just profit.

One thing that would be good is to get a FriendlyURL module. All the links on the site will still have the virtual directory in them but users will hardly ever notice them since when they click on them they will be redirected to the nice name.  Outbound rewrite rules would work if you run your own server but GoDaddy only has version 1.1 of the URLRewrite Module. If we could get them to upgrade to 2.0 we would be able to rewrite urls in links.