The Mighty Blog

Jan23

Written by:Will
1/23/2009  RssIcon

Here is a solution to a problem we were having with accepting the short form of our domain.

There's nothing wrong with accepting both "www.MyDomain.com" and "MyDomain.com", right?  Well, the answer can be yes.  But it may not be.  We ran into the latter...

We (RezHub.com) have a new DotNetNuke module that uses no server controls at all.  That's right. None.  It is completely HTML, JS, JSON, and jQuery.  It is an awesome custom module that was written for us by Arrow Designs (a.k.a. Arrow Nuke).  There are some really cool features that were improved upon greatly in comparison to our original search module. 

One of those features is the intellisense or auto-suggest feature in the textboxes. The previous module had a clunky but functional implementation.  This version has an incredibly fast and accurate version.  In the back end, it relies on calls using jQuery and JSON to retrieve data, depending on the keystrokes of the visitor.  It goes without saying, that we have a WCF web service sitting in the background listening for and responding to this request to fill the city information.

A well-known limitation (Microsoft calls it a security feature), is that WCF will only listen to one domain.  For example, this web service will only listen to either RezHub.com OR www.RezHub.com.  The one that is listened on depends on which URL is first used to hit the web service.  For example, if RezHub.com is used to hit the web service first, then www.RezHub.com will no longer respond.  In fact, the direct URL will return a HTTP 404 error.  This will happen in the opposite order, but same conditions if the service was first hit using www.RezHub.com.

Needless to say, that is an extremely frustrating scenario!  And I think we are all on the same boat if I were to say that this was an incredibly short-sighted implementation by the Microsoft team.  Ugh!  Talk about useless headaches and wasted developer hours!

There are many ways to deal with this, but the most elegant and universally friendly way to approach this appeared to be through the use of rewriting the URL.  Luckily, if you are using DotNetNuke, this is a feature that you are already using on each page request/response, and there is a provider model to plug in logic for this very specific scenario!  So, we have a framework in place that will already allow us to change any request beginning with "RezHub.com" to "www.RezHub.com" without having to rearchitect any of our existing code.

While you could just plug in your own HttpModule, I suggest recreating the UrlRewriteModule that is included in the core.  Just copy the class, and change the namespaces, then plug it in to your App_Code directory or existing assemblies.

Now, in the existing UrlRewriteModule code, there is a OnBeginRequest method.  Here is where all of the magic happens for DNN.  Near the top of this class, but below where the existing instantiations are, add the following code.

If Not Regex.IsMatch(app.Request.Url.AbsoluteUri, "^(http|https){1}://([A-Za-z0-9\-]+\.{1}){2}") And Not String.Equals(Request.ServerVariables("REMOTE_HOST"), "localhost") Then
    Response.StatusCode = 301
    Response.Status = "301 Moved Permanently"
    Response.AddHeader("Location", RewriteUrlForDomain(app.Request.Url.AbsoluteUri))
    Response.End()
End If

The previous code snippet will look at the domain name of the incoming request, and then determine if it has a subdomain or not.  For example, "www" will be considered a subdomain.  If there isn't a subdomain, and if the current request is not from the "localhost", then we will send the current URL to a sub method.  The submethod will be described in a moment.  Just know that once the submethod is called, the visitor is then sent back the headers we created, sending them to the new URL.  The 301 code will tell the web servers to get rid of the previous URL and index the new one.

Here is the code for the actual URL rewrite.

Private Function RewriteUrlForDomain(ByVal URL As String) As String
    If Not Regex.IsMatch(URL, "^(http|https){1}://([A-Za-z0-9\-]+\.{1}){2}") Then
        Return Regex.Replace(URL, "^(http://|https://){1}(.*)$", "$1www.$2")
    Else
        Return URL
    End If
End Function

In the previous code snippet, we once again look to see if there is a subdomain passed (important).  If there isn't, then add the "www." to the front of the domain name.

The final step is to add the required XML to your web.config to switch the DNN HttpModule out for your own.  Put it in the <system.web><httpModules> node collection.  Your snippet should look something like the following:

<add name="UrlRewrite" type="YourCompany.HttpModules.UrlRewriteModule, YourCompany.AssemblyName" />

That's it!  Now, all URLs will have the expected "www." in front of the URL when it is needed.

Technorati Tags: , , , ,

Copyright ©2009 Will Strohl

4 comment(s) so far...


Gravatar

Two thoughts:
1) having your domain setup to respond to either www.rezhub.com or rezhub.com is bad for seo (search engines see that as two different web addresses). you can get around this using IIS to setup a 301 redirect to via another IIS site to permanently redirect.
2) based on number 1, you shouldn't have had to update the url rewriter because iis would be permanently redirecting to site and your url would be fine.

am i missing something? it's cool coding nonetheless.

By Scott Allender on   1/25/2009
Gravatar

If you are only responding to 1 of the URLs and are in an environment where some sites shared IP numbers, that is not an option. As you know, we need both URLs to respond to visitors using either domain name.

By Will on   1/23/2009
Gravatar

A best way,

http://weblogs.asp.net/owscott/archive/2010/03.aspx

By Juliano on   6/14/2010
Gravatar

@Juliano: Hopefully, you know as I do, that there's no such thing as "the best way" to do things in IT. It always depends on the project requirements, business rules, and resources.

By Will on   6/14/2010

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
Add to Technorati Favorites
Tweet about my blog
Will Strohl - The Mighty Blog - RSS Feed

Tag Cloud

Sort by:Tag | SizeRSS
camp   community   dnn   dotnetnuke   dotnetnuke®   event   example   free   get   group   integer   jquery   meeting   module   odug   orlando   search   session   think   use  
The opinions expressed here are the personal opinions of Will Strohl and do not necessarily represent the views and opinions of the DotNetNuke Corporation.
© Copyright 2004-2010 by Will Strohl. All rights reserved.Website Skinned By: Ralph Williams  Website Hosted By: Applied Innovations