Dead Simple ASP.NET MVC Authentication

You may already know that, due to its lightweight architecture, ASP.NET MVC makes it simple to get a website up and running. But another advantage to such a manageable framework is how simple it is to implement any necessary component with just the bare minimum functionality.

One such requirement is the need to enforce Forms Authentication for your website. When creating a simple prototype, you’re probably not concerned with the specifics of the user security, implementation, but you probably do want to demonstrate it!

Read more at the Falafel Software Blog: Dead Simple ASP.NET MVC Authentication

Adding MySql.Data.MySqlClient to DBProviderFactories in ADO.NET

Today I had an opportunity to travel back in time all the way to 2005 and work with the classic ADO.NET classes in .NET. Needless to say, I’d forgotten everything about it…

The end goal was to create a control that can connect to different databases, even different types of databases, and execute the same SQL commands based on some condition. Basically it was, at last, that real-world scenario all the ASP.NET and C# books from back in the day said just might come up some day. It only took 8 years!

Anyway, my first step was to verify that I did indeed have all my data providers in the ADO.NET DbFactories, as I needed to cover SQL Server, Oracle, and MySQL. Fortunately I quickly found this old developer.com article which laid it out for me.

View full snippet on Gist.

When I ran that, I noticed that the MySql provider was missing, which was unexpected because I did have the MySql.Data assembly (which contains the MySql .Net Connector) in my project. After a bit more searching I found this helpful StackOverflow thread: ASP.NET and MySQL .Net Framework Data Provider Issues.

It reminded me that I also have to add that Provider to the system.data node in web.config, as shown here:

View full snippet on Gist.

Once I added that to my web.config, I was able to see it in the list of providers above.

Now I’m ready to rock!

Upgrading From Sitefinity 3: Url Rewriting

This post is part of a series exploring my migration from Sitefinity 3 to 4.4. Some of this information may become obsolete as newer versions are released. Always watch the official Sitefinity website for the latest info.

As part of the migration of my website from Sitefinity 3, I updated both the Url format for pages (now extensionless) and blog posts (also extensionless and different format) for better readability and SEO. This of course would leave a wake of broken links and search results linking to the old Urls.

There are many options available to resolve this, such as developing a custom HttpHandler to intercept the old Urls. Fortunately, there is a fantastic tool that handles all of this for you.

IIS Url Rewrite

IIS Url Rewrite is an extension for IIS that enables a wealth of Url handling features, including the two I needed for my site: Rewriting and Redirecting.

Redirects

As part of my website update, I moved some of the content such as the Sitefinity 3 Toolkit info to my company website Page Init Solutions. So I need to redirect all these requests from this site to that one.

The Url Rewrite module has an option for creating redirects, which you can manage in a friendly GUI for IIS.

IIS-UrlRewrite

You can also manage this directly in the web.config file. Here are some of the redirects I put in place using the module.

 <rewrite>
            <rules>
                <clear />
                <rule name="Redirect rule1 for PageInit">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{PageInit:{REQUEST_URI}}" pattern="(.+)" />
                    </conditions>
                    <action type="Redirect" url="{C:1}" appendQueryString="false" />
                </rule>
            </rules>
            <rewriteMaps>
                <rewriteMap name="PageInit">
                    <add key="/software.aspx" value="http://pageinit.net/software" />
                    <add key="/software/Sitefinity/Sitefinity_Toolkit.aspx" value="http://pageinit.net/software/sitefinity-toolkit" />
                    <add key="/software/jQuery/Banner_Swapper.aspx" value="http://pageinit.net/software/jquery-banner-swapper" />
                    <add key="/software/Sitefinity/Sitefinity_Password_Recovery.aspx" value="http://pageinit.net/software/sitefinity-3-password-recovery-tool" />
                    <add key="/blog.aspx" value="http://www.selarom.net/blog" />
                    <add key="/contact.aspx" value="http://www.selarom.net/contact" />
                </rewriteMap>
            </rewriteMaps>
      </rewrite>

This allowed me to easily map old Urls to new, including the old .aspx extensions for pages. Adding a new redirect is as simple as adding a new entry in the list.

Url Rewriting

The new blog Url format makes for SEO friendly as well as functionally useful Urls. They are, however, starkly different from the original format from Sitefinity 3, and clearly, redirecting every single post individually is not an ideal solution.

Fortunately, the Url Rewrite Module also has excellent support for Url rewriting using Regular Expressions. Using Regex, I was able to easily rewrite the old format of /YYYY-MM-DD/Title to the new /YYYY/MM/DD/Title format now used by Sitefinity. I was even able to rewrite some of the urls for the list of blogs by Tag and Category.

Admittedly, working with Regular Expressions is probably one of my weakest programming skills, and despite what everyone keeps saying on Twitter, it does NOT get easier the more you do it! That being said, here are the Regex rewrites I created for this site. If anyone has suggestions for improving or consolodating them, by all means let me know!

 <rule name="BlogPosts" stopProcessing="true">
                    <match url="^(.*)/([0-9]{4})[-]([0-9]{2})[-]([0-9]{2})/(.*)$" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Redirect" url="{R:1}/{R:2}/{R:3}/{R:4}/{R:5}" />
                </rule>
                <rule name="BlogYear2Month">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="Year=([0-9]{4})" />
                        <add input="##{C:1}##_{QUERY_STRING}" pattern="##([^#]+)##_.*Month=(\d{2})" />
                    </conditions>
                    <action type="Redirect" url="blog/{C:1}/{C:2}" appendQueryString="false"/>
                </rule>
                <rule name="BlogYear1Month">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="Year=([0-9]{4})" />
                        <add input="##{C:1}##_{QUERY_STRING}" pattern="##([^#]+)##_.*Month=(\d{1})" />
                    </conditions>
                    <action type="Redirect" url="blog/{C:1}/0{C:2}" appendQueryString="false"/>
                </rule>
                <rule name="BlogYear">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="Year=([0-9]{4})" />
                    </conditions>
                    <action type="Redirect" url="blog/{C:1}" appendQueryString="false"/>
                </rule>
                <rule name="BlogTag">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="tag=(.*)" />
                    </conditions>
                    <action type="Redirect" url="/blog/-in-Tags/Tags/{C:1}" appendQueryString="false"/>
                </rule>

Wrapping Up

The IIS Url Rewrite Module is a fantastic tool for ANY website that has a need for rewriting or maintaining Urls, and is highly recommended for anyone attempting to migrate to the latest verion of Sitefinity.

Finally, here are a few resources I found extremely helpful in preparing these rewrites and redirects:

Overriding ASP.NET Theme CSS Files with Conditional Comments

One of the biggest annoyances in ASP.NET is the way it adds CSS files to your <head> element of your pages. It insists on adding them to the end, offering you no way to add your own custom styles that override the theme unless you go down the line and add !important to each element.

This is especially detrimental if you’re trying to add IE-only stylesheets using conditional comments. Since the theme files are loaded after the IE stylesheet, all your custom styles will be overridden as if it was not present at all.

There are some hacks, from using the script manager to inject css (which doesn’t work because this doesn’t inject it into the <head> section) to a full fledged custom control that automates this for you.

I needed something quick and dirty, so I hacked a solution by overriding the Render method of the site’s Master Page and injecting an HTML Literal control with the IE conditional comments.

protected override void Render(HtmlTextWriter writer)
{
    // IE conditionals string css = @" <!--[if IE]> <link rel=""stylesheet"" type=""text/css"" href=""/css/ie.css"" /> <![endif]--> ";
    // add conditional text to head var ctrl = new Literal();
    ctrl.Text = css;
    Head1.Controls.Add(ctrl);
    base.Render(writer);
}

Apparently this is late enough in the page life-cycle to be added after the Theme files, and it works like a charm!

I thought this was addressed in 4.0, but I can’t seem to find anywhere to specify a custom location for the theme css files, nor any simple way to specify additional files afterwards. If there is a simple, built-in solution to this problem, please let me know in the comments!