<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SquaredRoot &#187; open source</title>
	<atom:link href="http://www.squaredroot.com/tag/open-source/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.squaredroot.com</link>
	<description>.Net Development in DC</description>
	<lastBuildDate>Sun, 16 Aug 2009 01:30:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>MVC Membership Starter Kit Released</title>
		<link>http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/</link>
		<comments>http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/#comments</comments>
		<pubDate>Fri, 07 Aug 2009 04:02:43 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.squaredroot.com/?p=538</guid>
		<description><![CDATA[Almost six months after the official release of Asp.Net MVC 1.0 and nearly a year after the last release of the starter kit, I've finally rewritten and released the Asp.Net MVC Membership Starter Kit.]]></description>
			<content:encoded><![CDATA[<p>Almost six months after the <a href="http://haacked.com/archive/2009/03/18/aspnet-mvc-rtw.aspx">official release of Asp.Net MVC 1.0</a> and nearly a year after <a href="http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/">the last release of the starter kit</a>, I&#8217;ve finally rewritten and released the Asp.Net MVC Membership Starter Kit. If you&#8217;re already familiar with what it is and want to grab it, you can find the release on the <a href="http://mvcmembership.codeplex.com">CodePlex project site</a>:</p>
<p><a href="http://mvcmembership.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=22875">http://mvcmembership.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=22875</a></p>
<p><span id="more-538"></span></p>
<h2>What is the Asp.Net MVC Membership Starter Kit?</h2>
<p>The starter kit currently consists of two things:</p>
<ol>
<li>A sample website containing the controllers, models, and views needed to administer users &amp; roles.</li>
<li>A library that provides testable interfaces for administering users &amp; roles and concrete implementations of those interfaces that wrap the built-in Asp.Net Membership &amp; Roles providers.</li>
</ol>
<p>Out of the box, the starter kit gives you the following features:</p>

<a href='http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/mvcmembership-user-list/' title='List of Users'><img width="150" height="150" src="http://www.squaredroot.com/wp-content/uploads/2009/08/MvcMembership-User-List-150x150.PNG" class="attachment-thumbnail" alt="List of Users" title="List of Users" /></a>
<a href='http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/mvcmembership-role-list/' title='List of Roles'><img width="150" height="150" src="http://www.squaredroot.com/wp-content/uploads/2009/08/MvcMembership-Role-List-150x150.PNG" class="attachment-thumbnail" alt="List of Roles" title="List of Roles" /></a>
<a href='http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/mvcmembership-user-account/' title='User Account Info'><img width="150" height="150" src="http://www.squaredroot.com/wp-content/uploads/2009/08/MvcMembership-User-Account-150x150.PNG" class="attachment-thumbnail" alt="User Account Info" title="User Account Info" /></a>
<a href='http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/mvcmembership-email-and-comments/' title='Change Email Address'><img width="150" height="150" src="http://www.squaredroot.com/wp-content/uploads/2009/08/MvcMembership-Email-and-Comments-150x150.PNG" class="attachment-thumbnail" alt="Change Email Address" title="Change Email Address" /></a>
<a href='http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/mvcmembership-user-roles/' title='Change a User&#039;s Roles'><img width="150" height="108" src="http://www.squaredroot.com/wp-content/uploads/2009/08/MvcMembership-User-Roles-150x108.PNG" class="attachment-thumbnail" alt="Change a User&#039;s Roles" title="Change a User&#039;s Roles" /></a>

<h2>How do I use it?</h2>
<p>In Asp.Net MVC 1 there isn&#8217;t a great story for packaging &amp; sharing controllers, views, and other resources so we&#8217;ll need to follow a few manual steps:</p>
<ol>
<li>After getting the source code build it using your preferred IDE or using the included <strong>Build.Debug.bat</strong> or <strong>Build.Release.bat</strong> batch files.</li>
<li>Grab the <strong>MvcMembership.dll</strong> assembly and place it wherever you&#8217;re including external libraries in your project. Add a reference to the assembly to your Asp.Net MVC application.</li>
<li>Copy the <strong>UserAdministrationController.cs</strong> file from the <em>SampleWebsite</em>&#8216;s <em>Controllers </em>directory to your app&#8217;s <em>Controllers </em>directory.</li>
<li>Copy the <strong>ISmtpClient.cs</strong> file, <strong>SmtpClientProxy.cs</strong> file, and <strong>UserAdministration</strong> folder from the <em>SampleWebsite</em>&#8216;s <em>Models </em>folder to your app&#8217;s <em>Models </em>folder.</li>
<li>Copy the <strong>UserAdministration</strong> folder from the <em>SampleWebsite</em>&#8216;s <em>Views </em>folder to your app&#8217;s <em>Views </em>folder.</li>
<li>Make sure you&#8217;ve configured your <strong>web.config</strong> properly for Membership and Roles. If you aren&#8217;t sure of how to do this, take a look at the first two articles in <a href="http://www.4guysfromrolla.com/articles/120705-1.aspx">this series by Scott Mitchell at 4GuysFromRolla</a>.</li>
<li>Finally, add the following code to your <strong>global.asax</strong> to keep the membership system updated with each user&#8217;s last activity date:</li>
</ol>
<pre class="brush: csharp">protected void Application_AuthenticateRequest()
{
	if(User != null)
		Membership.GetUser(true);
}</pre>
<h2>What is new since the last release?</h2>
<p>Well, the last release was for <a href="http://mvcmembership.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=16809">Preview 5</a>, so at the very least the project has been updated for Beta and finally Release. Moreover, the project has been completely rewritten from scratch &#8211; a major undertaking that was the primary cause of the long delay between releases. Why the rewrite? Two reasons:</p>
<ol>
<li>The <a href="http://mvcmembership.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=12215">first release of the Starter Kit</a> was for Preview 2 of the MVC framework. A lot changed between Preview 2 and Release &#8211; A LOT. A lot of the features of the first starter kit were rolled into the OTOB experience (such as login and registration), so I shifted the scope of the project more squarely into the realm of user &amp; role administration. Unfortunately all of these major changes took a toll on the source &#8211; I was no longer happy working in the source as it was written for many reasons and thus wanted a rewrite. One of those reasons was&#8230;</li>
<li>Previous releases had no (as in zero, less than one, nada) unit tests. This became increasingly unacceptable to me and trying to add unit tests after-the-fact was a nightmare. Instead I rewrote the project using TDD.</li>
</ol>
<p>Alright, so that was basically the long-winded spiel to prepare you for the bad news: the project regressed from a functionality perspective. During the course of the rewrite things some things didn&#8217;t make it in &#8211; chief among them is the OpenID integration. I encourage everyone to take a look at the Maarten Balliauw (an MvcMembership contributor) blog post on <a href="http://blog.maartenballiauw.be/post/2009/07/27/Authenticating-users-with-RPXNow-%28in-ASPNET-MVC%29.aspx">authenticating via RPX in MVC</a>.</p>
<h2>What comes next?</h2>
<p>The primary motivator for me getting off my but after nearly a year and finishing up this release is my desire to convert it to an <a href="http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx">&#8220;area&#8221; for use in MVC 2</a>. Packaging reusable components like this has been a sore spot for the current MVC framework and I&#8217;m glad to see the blue badges are going to provide a common solution. Along with that I&#8217;ll likely try to add RPX authentication ala Maarten&#8217;s post. </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>Return of the PagedList</title>
		<link>http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/</link>
		<comments>http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 10:00:40 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[CodePlex]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[paging]]></category>

		<guid isPermaLink="false">http://www.squaredroot.com/?p=462</guid>
		<description><![CDATA[A few days ago, Craig Stuntz reported an interesting observation: when the first page is returned, the class performs a Skip(0). Suprisingly, this is not free. With that in mind, I set out to correct that issue as well as incorporate a few changes I've made over the past year. The result is nearly identical to the last posted version, just a bit more readable. Additionally...]]></description>
			<content:encoded><![CDATA[<p>It has been nearly a year since I <a href="http://www.squaredroot.com/2008/07/08/PagedList-Strikes-Back/">posted</a> an updated version of the PagedList&lt;T&gt; functionality originally <a href="http://blog.wekeroad.com/blog/aspnet-mvc-pagedlistt">created by Scott Guthrie and posted by Rob Conery</a>. Since then I have used the class in a number of projects and find it indispensable.</p>
<p>A few days ago, Craig Stuntz reported an interesting observation: when the first page is returned, the class performs a Skip(0). Suprisingly, <a href="http://blogs.teamb.com/craigstuntz/2009/06/10/38313/">this is not free</a>. With that in mind, I set out to correct that issue as well as incorporate a few changes I&#8217;ve made over the past year. The result is nearly identical to the last posted version, just a bit more readable. Additionally&#8230;<br />
<span id="more-462"></span></p>
<ul>
<li>The source is now available on CodePlex: <a href="http://pagedlist.codeplex.com">http://pagedlist.codeplex.com</a>. This should make finding and downloading the code easier than finding the correct blog entry on some dude&#8217;s blog.</li>
<li>I have posted a release-compiled, XML commented, signed assembly on CodePlex. I got tired of having to copy the source into multiple projects and finding a place to put it in that project&#8217;s taxonomy.</li>
<li>Further incremental changes can be found in the Change Log on the CodePlex project site.</li>
</ul>
<h3><a href="http://pagedlist.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28585#ReleaseFiles">Download from CodePlex</a></h3>
<p></p>
<h4>IPagedList&lt;T&gt;.cs</h4>
<pre class="brush: csharp">using System.Collections.Generic;

namespace PagedList
{
	public interface IPagedList&lt;T&gt; : IList&lt;T&gt;
	{
		int PageCount { get; }
		int TotalItemCount { get; }
		int PageIndex { get; }
		int PageNumber { get; }
		int PageSize { get; }
		bool HasPreviousPage { get; }
		bool HasNextPage { get; }
		bool IsFirstPage { get; }
		bool IsLastPage { get; }
	}
}</pre>
<h4>PagedList&lt;T&gt;.cs</h4>
<pre class="brush: csharp">using System;
using System.Collections.Generic;
using System.Linq;

namespace PagedList
{
	public class PagedList&lt;T&gt; : List&lt;T&gt;, IPagedList&lt;T&gt;
	{
		public PagedList(IEnumerable&lt;T&gt; superset, int index, int pageSize)
		{
			// set source to blank list if superset is null to prevent exceptions
			var source = superset == null
			                      	? new List&lt;T&gt;().AsQueryable()
									: superset.AsQueryable();

			TotalItemCount = source.Count();
			PageSize = pageSize;
			PageIndex = index;
			if (TotalItemCount &gt; 0)
				PageCount = (int) Math.Ceiling(TotalItemCount/(double) PageSize);
			else
				PageCount = 0;

			if (index &lt; 0)
				throw new ArgumentOutOfRangeException("index", index, "PageIndex cannot be below 0.");
			if (pageSize &lt; 1)
				throw new ArgumentOutOfRangeException("pageSize", pageSize, "PageSize cannot be less than 1.");

			// add items to internal list
			if (TotalItemCount &gt; 0)
				if (index == 0)
					AddRange(source.Take(pageSize).ToList());
				else
					AddRange(source.Skip((index) * pageSize).Take(pageSize).ToList());
		}

		public int PageCount { get; private set; }
		public int TotalItemCount { get; private set; }
		public int PageIndex { get; private set; }
		public int PageSize { get; private set; }

		public int PageNumber
		{
			get { return PageIndex + 1; }
		}

		public bool HasPreviousPage
		{
			get { return PageIndex &gt; 0; }
		}

		public bool HasNextPage
		{
			get { return PageIndex &lt; (PageCount - 1); }
		}

		public bool IsFirstPage
		{
			get { return PageIndex &lt;= 0; }
		}

		public bool IsLastPage
		{
			get { return PageIndex &gt;= (PageCount - 1); }
		}
	}
}</pre>
<h4>PagedListExtensions.cs</h4>
<pre class="brush: csharp">using System.Collections.Generic;
using System.Linq;

namespace PagedList
{
	public static class PagedListExtensions
	{
		public static IPagedList&lt;T&gt; ToPagedList&lt;T&gt;(this IEnumerable&lt;T&gt; superset, int index, int pageSize)
		{
			return new PagedList&lt;T&gt;(superset, index, pageSize);
		}
	}
}</pre>
<h4>PagedListFacts.cs</h4>
<pre class="brush: csharp; collapse: true">using System;
using System.Collections.Generic;
using Xunit;
using Xunit.Extensions;

namespace PagedList.Tests
{
	public class PagedListFacts
	{
		[Fact]
		public void Null_Data_Set_Doesnt_Throw_Exception()
		{
			//act
			Assert.ThrowsDelegate act = () =&gt; new PagedList&lt;object&gt;(null, 0, 10);

			//assert
			Assert.DoesNotThrow(act);
		}

		[Fact]
		public void PageIndex_Below_Zero_Throws_ArgumentOutOfRange()
		{
			//arrange
			var data = new[] {1, 2, 3};

			//act
			Assert.ThrowsDelegate act = () =&gt; data.ToPagedList(-1, 1);

			//assert
			Assert.Throws&lt;ArgumentOutOfRangeException&gt;(act);
		}

		[Fact]
		public void PageIndex_Above_RecordCount_Returns_Empty_List()
		{
			//arrange
			var data = new[] {1, 2, 3};

			//act
			var pagedList = data.ToPagedList(2, 3);

			//assert
			Assert.Equal(0, pagedList.Count);
		}

		[Fact]
		public void PageSize_Below_One_Throws_ArgumentOutOfRange()
		{
			//arrange
			var data = new[] {1, 2, 3};

			//act
			Assert.ThrowsDelegate act = () =&gt; data.ToPagedList(0, 0);

			//assert
			Assert.Throws&lt;ArgumentOutOfRangeException&gt;(act);
		}

		[Fact]
		public void Null_Data_Set_Doesnt_Return_Null()
		{
			//act
			var pagedList = new PagedList&lt;object&gt;(null, 0, 10);

			//assert
			Assert.NotNull(pagedList);
		}

		[Fact]
		public void Null_Data_Set_Returns_Zero_Pages()
		{
			//act
			var pagedList = new PagedList&lt;object&gt;(null, 0, 10);

			//assert
			Assert.Equal(0, pagedList.PageCount);
		}

		[Fact]
		public void Zero_Item_Data_Set_Returns_Zero_Pages()
		{
			//arrange
			var data = new List&lt;object&gt;();

			//act
			var pagedList = data.ToPagedList(0, 10);

			//assert
			Assert.Equal(0, pagedList.PageCount);
		}

		[Fact]
		public void DataSet_Of_One_Through_Five_PageSize_Of_Two_PageIndex_Of_One_First_Item_Is_Three()
		{
			//arrange
			var data = new[] {1, 2, 3, 4, 5};

			//act
			var pagedList = data.ToPagedList(1, 2);

			//assert
			Assert.Equal(3, pagedList[0]);
		}

		[Fact]
		public void TotalCount_Is_Preserved()
		{
			//arrange
			var data = new[] {1, 2, 3, 4, 5};

			//act
			var pagedList = data.ToPagedList(1, 2);

			//assert
			Assert.Equal(5, pagedList.TotalItemCount);
		}

		[Fact]
		public void PageIndex_Is_Preserved()
		{
			//arrange
			var data = new[] {1, 2, 3, 4, 5};

			//act
			var pagedList = data.ToPagedList(1, 2);

			//assert
			Assert.Equal(1, pagedList.PageIndex);
		}

		[Fact]
		public void PageSize_Is_Preserved()
		{
			//arrange
			var data = new[] {1, 2, 3, 4, 5};

			//act
			var pagedList = data.ToPagedList(1, 2);

			//assert
			Assert.Equal(2, pagedList.PageSize);
		}

		[Fact]
		public void Data_Is_Filtered_By_PageSize()
		{
			//arrange
			var data = new[] {1, 2, 3, 4, 5};

			//act
			var pagedList = data.ToPagedList(1, 2);

			//assert
			Assert.Equal(2, pagedList.Count);

			//### related test below

			//act
			pagedList = data.ToPagedList(2, 2);

			//assert
			Assert.Equal(1, pagedList.Count);
		}

		[Fact]
		public void DataSet_OneThroughSix_PageSize_Three_PageIndex_Zero_FirstValue_Is_One()
		{
			//arrange
			var data = new[] { 1, 2, 3, 4, 5, 6 };

			//act
			var pagedList = data.ToPagedList(0, 3);

			//assert
			Assert.Equal(1, pagedList[0]);
		}

		[Fact]
		public void DataSet_OneThroughThree_PageSize_One_PageIndex_Two_HasNextPage_False()
		{
			//arrange
			var data = new[] {1, 2, 3};

			//act
			var pagedList = data.ToPagedList(2, 1);

			//assert
			Assert.Equal(false, pagedList.HasNextPage);
		}

		[Fact]
		public void DataSet_OneThroughThree_PageSize_One_PageIndex_Two_IsLastPage_True()
		{
			//arrange
			var data = new[] {1, 2, 3};

			//act
			var pagedList = data.ToPagedList(2, 1);

			//assert
			Assert.Equal(true, pagedList.IsLastPage);
		}

		[Fact]
		public void DataSet_OneAndTwo_PageSize_One_PageIndex_One_FirstValue_Is_Two()
		{
			//arrange
			var data = new[] { 1, 2 };

			//act
			var pagedList = data.ToPagedList(1, 1);

			//assert
			Assert.Equal(2, pagedList[0]);
		}

		[Theory]
		[InlineData(new[] {1, 2, 3}, 0, 1)]
		[InlineData(new[] {1, 2, 3}, 1, 2)]
		[InlineData(new[] {1, 2, 3}, 2, 3)]
		public void Theory_PageNumber_Is_PageIndex_Plus_One(int[] integers, int pageIndex, int expectedPageNumber)
		{
			//arrange
			var data = integers;

			//act
			var pagedList = data.ToPagedList(pageIndex, 1);

			//assert
			Assert.Equal(expectedPageNumber, pagedList.PageNumber);
		}

		[Theory]
		[InlineData(new[] {1, 2, 3}, 0, 1, false, true)]
		[InlineData(new[] {1, 2, 3}, 1, 1, true, true)]
		[InlineData(new[] {1, 2, 3}, 2, 1, true, false)]
		public void Theory_HasPreviousPage_And_HasNextPage_Are_Correct(int[] integers, int pageIndex, int pageSize,
		                                                               bool expectedHasPrevious, bool expectedHasNext)
		{
			//arrange
			var data = integers;

			//act
			var pagedList = data.ToPagedList(pageIndex, pageSize);

			//assert
			Assert.Equal(expectedHasPrevious, pagedList.HasPreviousPage);
			Assert.Equal(expectedHasNext, pagedList.HasNextPage);
		}

		[Theory]
		[InlineData(new[] {1, 2, 3}, 0, 1, true, false)]
		[InlineData(new[] {1, 2, 3}, 1, 1, false, false)]
		[InlineData(new[] {1, 2, 3}, 2, 1, false, true)]
		public void Theory_IsFirstPage_And_IsLastPage_Are_Correct(int[] integers, int pageIndex, int pageSize,
		                                                          bool expectedIsFirstPage, bool expectedIsLastPage)
		{
			//arrange
			var data = integers;

			//act
			var pagedList = data.ToPagedList(pageIndex, pageSize);

			//assert
			Assert.Equal(expectedIsFirstPage, pagedList.IsFirstPage);
			Assert.Equal(expectedIsLastPage, pagedList.IsLastPage);
		}

		[Theory]
		[InlineData(new[] {1, 2, 3}, 1, 3)]
		[InlineData(new[] {1, 2, 3}, 3, 1)]
		[InlineData(new[] {1}, 1, 1)]
		[InlineData(new[] {1, 2, 3}, 2, 2)]
		[InlineData(new[] {1, 2, 3, 4}, 2, 2)]
		[InlineData(new[] {1, 2, 3, 4, 5}, 2, 3)]
		public void Theory_PageCount_Is_Correct(int[] integers, int pageSize, int expectedNumberOfPages)
		{
			//arrange
			var data = integers;

			//act
			var pagedList = data.ToPagedList(0, pageSize);

			//assert
			Assert.Equal(expectedNumberOfPages, pagedList.PageCount);
		}
	}
}</pre>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2009/06/15/return-of-the-pagedlist/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>MVC Membership &#8211; Preview 5</title>
		<link>http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/</link>
		<comments>http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/#comments</comments>
		<pubDate>Sat, 06 Sep 2008 13:15:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2008/09/06/MVC-Membership-Preview-5.aspx</guid>
		<description><![CDATA[Last weekend I posted a release of the MVC Membership Starter Kit that targets Preview 5 of the ASP.Net MVC framework. There was no packaged release targeting Preview 4 (though if you downloaded the latest source, it worked), so this release essentially packages the changes from both previews. Why does the MVC Membership Starter Kit [...]]]></description>
			<content:encoded><![CDATA[<p>Last weekend I posted a release of the MVC Membership Starter Kit that targets <a href="http://haacked.com/archive/2008/08/29/asp.net-mvc-codeplex-preview-5-released.aspx">Preview 5 of the ASP.Net MVC framework</a>. There was no packaged release targeting <a href="http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx">Preview 4</a> (though if you <a href="http://www.codeplex.com/MvcMembership/SourceControl/ListDownloadableCommits.aspx">downloaded the latest source</a>, it worked), so this release essentially packages the changes from both previews.<span id="more-12"></span></p>
<h2>Why does the MVC Membership Starter Kit still exist?</h2>
<p>The biggest change affecting the MVC Membership Starter Kit is that the default ASP.Net MVC Web Application project includes <a href="http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx">login/logout, register, and change password functionality as of Preview 4</a>. This is great and I’m glad to see them do it. It is my hope they will eventually include membership administration functionality as well. For now, however, they haven’t included it. This leaves three main features that are now driving the existence of this project:</p>
<ol>
<li><strong>Membership Administration</strong><br />
What good is registration, login, and logout if a site’s owner cannot change a user’s roles or manage their user base? While Visual Studio’s <a href="http://msdn.microsoft.com/en-us/library/yy40ytx0.aspx">Web Site Administration Tool</a> covers most of your bases during development, it isn’t a real option for use by web site administrators in a production application.</li>
<li><strong>OpenID Integration</strong><br />
Preview 4’s built-in login functionality only covers the use of standard username/password authentication. It seems likely that this will continue, as I am not aware of any plans for official <a href="http://openid.net/">OpenID</a> support within the .Net framework. We are using <a href="http://code.google.com/p/dotnetopenid/">Andrew Arnott &amp; co’s DotNetOpenId</a> project to help you let your users log in using OpenID.</li>
<li><strong>WindowsLive LiveID Integration</strong><br />
<a href="http://blog.maartenballiauw.be/">Maarten</a>’s <a href="http://dev.live.com/liveid/">LiveID</a> integration has unfortunately not made this release. I anticipate that it will be available again for the next release, which will target <a href="http://haacked.com/archive/2008/09/05/mvcfutures-and-asp.net-mvc-beta.aspx">the first beta release of ASP.Net MVC</a>.</li>
</ol>
<h2>What has changed?</h2>
<ol>
<li><strong>No more login/logout/password retrieval.</strong><br />
Because the AccountController and its views are now included by default in new projects, the need for this functionality has gone away.</li>
<li><strong>Less assemblies to reference.</strong><br />
Rather than the MembershipAdministrationController and other code being compiled into a separate assembly that you must include, you now drop the controllers directly into your web app. This allows you to easily change the code as your project evolves. The starter kit’s implementation is really just a starting point that you can build off of.</li>
<li><strong>Controllers are split.</strong><br />
In previous releases the OpenID and WindowsLive login functionality was included in the MembershipAuthenticationController. The OpenID functionality has since been moved into a separate controller with separate views. This was done because (a) the MembershipAuthenticationController no longer exists and (b) moving forward more of the pieces of this kit will be separated from each other so that you can include them a la carte.</li>
</ol>
<h2>Download</h2>
<p>You can download the Preview 5 release of the MVC Membership Starter Kit from CodePlex:</p>
<p><a title="http://www.codeplex.com/MvcMembership/Release/ProjectReleases.aspx?ReleaseId=16809#ReleaseFiles" href="http://www.codeplex.com/MvcMembership/Release/ProjectReleases.aspx?ReleaseId=16809#ReleaseFiles">http://www.codeplex.com/MvcMembership…?ReleaseId=16809</a> </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/09/06/mvc-membership-preview-5/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>MVC Membership &#8211; Preview 3</title>
		<link>http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/</link>
		<comments>http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 04:15:29 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2008/07/02/MVC-Membership-Preview-3.aspx</guid>
		<description><![CDATA[Tonight we posted a new release of the MVC Membership Starter Kit. This release is an update to migrate the starter kit to the new Preview 3 release of the MVC framework. While several bugs have been squashed, no major new functionality has been added. If you couldn&#8217;t wait and downloaded the source prior to [...]]]></description>
			<content:encoded><![CDATA[<p>Tonight we posted a <a href="http://www.codeplex.com/MvcMembership/Release/ProjectReleases.aspx?ReleaseId=14919">new release of the MVC Membership Starter Kit</a>. This release is an update to migrate the starter kit to <a href="http://weblogs.asp.net/scottgu/archive/2008/05/27/asp-net-mvc-preview-3-release.aspx">the new Preview 3 release of the MVC framework</a>. While several bugs have been squashed, no major new functionality has been added.</p>
<p>If you couldn&#8217;t wait and downloaded the source prior to the official Preview 3 release, you&#8217;ll still want to download tonight&#8217;s official release as several important issues have been addressed.</p>
<p><strong>Bug Fixes in 1.3:</strong></p>
<ul>
<li>The System.Web.Abstraction, System.Web.Mvc, and System.Web.Routing DLLs being used prior to tonight were from an earlier Preview 3 release and were not signed by Microsoft. </li>
<li>Routing ambiguities caused a 404 error to occur when a user enters an incorrect username/password combination on the login page. </li>
<li>Several errors were occurring on various password recovery screens which created a bad user experience. </li>
<li>Errors on the administration section&#8217;s Create User and Display User pages were preventing that functionality from working at all. </li>
</ul>
<p>Thanks for all of the interest everyone has shown in this project and thanks to <a href="http://blog.maartenballiauw.be/">Maarten</a> and <a href="http://gregorybeamer.spaces.live.com/blog/">Greg</a> for their contributions; especially to Maarten as he did most of the grunt work in upgrading our code base to Preview 3. Please send any feedback you have our way, we&#8217;d love to hear it!</p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/07/02/mvc-membership-preview-3/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Help Decide Sandcastle&#8217;s Fate</title>
		<link>http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/</link>
		<comments>http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/#comments</comments>
		<pubDate>Tue, 10 Jun 2008 19:58:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[CodePlex]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2008/06/10/Sandcastle-Removed-From-CodePlex.aspx</guid>
		<description><![CDATA[Sandcastle &#8211; the .Net community equivalent of RDoc/JavaDoc and the spiritual successor of the now defunct NDoc &#8211; has been removed from CodePlex. It&#8217;s fate is currently up in the air and Microsoft is asking you for input on what should happen next. It was pulled down after the community at-large expressed reservations about Sandcastle [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://articles.techrepublic.com.com/5100-10878_11-6174811.html">Sandcastle</a> &#8211; the .Net community equivalent of <a href="http://rdoc.sourceforge.net/">RDoc</a>/<a href="http://java.sun.com/j2se/javadoc/">JavaDoc</a> and the spiritual successor of the now defunct <a href="http://ndoc.sourceforge.net/">NDoc</a> &ndash; <a href="http://blogs.msdn.com/sandcastle/archive/2008/06/06/sandcastle-project-removed-from-codeplex.aspx">has been removed from CodePlex</a>. It&rsquo;s fate is currently up in the air and Microsoft is asking you for input on what should happen next. It was pulled down after the community at-large expressed reservations about Sandcastle being hosted on <a href="http://www.codeplex.com">CodePlex</a> while not being published under an Open Source license or even being posted in source form at all. According to the announcement on MSDN, the possible future for Sandcastle involves two scenarios:
</p>
<blockquote>
<ol>
<li>
<p>
		Publish the source code for Sandcastle and revive this project in Codeplex
		</p>
</li>
<li>
<p>
		Migrate sandcastle to MSDN Code gallery at <a href="http://code.msdn.microsoft.com/">http://code.msdn.microsoft.com</a>
		</p>
</li>
</ol>
</blockquote>
<p>
I for one would love to see Sandcastle released as an open source project on CodePlex. It seems to me that Microsoft has had a great deal of success lately with releasing the MVC Framework as an open source project and I hope that they continue the trend. If you have used Sandcastle or foresee the need to have automatic code documentation generation on a project in the future, please do not hesitate to <a href="http://blogs.msdn.com/sandcastle/archive/2008/06/06/sandcastle-project-removed-from-codeplex.aspx">leave a comment</a> letting the powers that be know how you feel.</p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/06/10/sandcastle-removed-from-codeplex/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>MVC Membership Starter Kit &#8211; 1.2</title>
		<link>http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/</link>
		<comments>http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 21:22:04 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2008/04/28/MVC-Membership-Starter-Kit-1-2.aspx</guid>
		<description><![CDATA[This weekend I posted a new release of the MVC Membership Starter Kit. This release is an update to migrate the starter kit to the new interim release of the MVC framework. If you do not feel comfortable using the interim release, please continue using the 1.1 release and wait for Microsoft to release Preview [...]]]></description>
			<content:encoded><![CDATA[<p>This weekend I posted a <a href="https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=MvcMembership&amp;ReleaseId=12667">new release of the MVC Membership Starter Kit</a>. This release is an update to migrate the starter kit to <a href="http://weblogs.asp.net/scottgu/archive/2008/04/16/asp-net-mvc-source-refresh-preview.aspx">the new interim release of the MVC framework</a>. If you do not feel comfortable using the interim release, please continue using the 1.1 release and wait for Microsoft to release Preview 3; we will update the Starter Kit soon thereafter.</p>
<h3>Changes in 1.2:</h3>
<ul>
<li>WindowsLive is now a supported authentication scenario (<a href="http://blog.maartenballiauw.be/post/2008/04/ASPNet-MVC-Membership-Starter-Kit-alternative-authentication.aspx">read Maarten&#8217;s blog post on this</a>). </li>
<li>Per <a href="http://blog.nerdbank.net/">Andrew Arnott&#8217;s</a> suggestion, the starter kit now uses the <a href="http://code.google.com/p/dotnetopenid/">DotNetOpenId</a> library rather than the code previously used (which was created by Mads Kristensen). This gives us a more robust and secure implementation that will develop and improve independently of this project.</li>
<li>All actions that previously expected a username in the route now expect the user&#8217;s ProviderUserKey (a Guid) instead. This was done because users with OpenID urls as their username could not previously be accessed. </li>
<li>&quot;Whitelist support&quot; has been added to the OpenID implementation, allowing you to setup regular expressions that dictate which OpenID providers are allowed to be used when logging into your site. By default there is no whitelist, so all providers are allowed. </li>
<li>The starter kit now offers greater control over which authentication scenarios your site supports and which is the default. Out-of-the-box only FormsAuthentication is enabled and is obviously the default. </li>
</ul>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/04/28/mvc-membership-starter-kit-1-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>MVC: New Membership Starter Kit Release</title>
		<link>http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/</link>
		<comments>http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 16:19:21 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2008/04/11/MVC-Membership-Starter-Kit-11.aspx</guid>
		<description><![CDATA[The Starter Kit If you haven&#8217;t had a chance to read about the MVC Membership Starter Kit I&#8217;ve created, read this post first. New Release Since we first created the starter kit a week and a half ago, Maarten Balliauw and I have been hard at work fleshing out the implementation to provide as much [...]]]></description>
			<content:encoded><![CDATA[<h2>The Starter Kit</h2>
<p>If you haven&#8217;t had a chance to read about the MVC Membership Starter Kit I&#8217;ve created, <a href="http://www.squaredroot.com/post/2008/04/MVC-Membership-Starter-Kit.aspx">read this post first</a>.</p>
<h2>New Release</h2>
<p>Since we first created the starter kit a week and a half ago, <a href="http://blog.maartenballiauw.be/">Maarten Balliauw</a> and I have been hard at work fleshing out the implementation to provide as much functionality as possible. Last night we finished the last stretch of things we had identified for this release and have posted the code as a new release on CodePlex. Keep in mind you can also always download our latest builds from CodePlex as well without waiting for a new release.</p>
<h2>New Features</h2>
<h3>OpenID</h3>
<p>Mads Kristensen <a href="http://blog.madskristensen.dk/post/OpenID-implementation-in-Csharp-and-ASPNET.aspx">released a lightweight OpenID consumer</a> earlier this year that I then proceeded to flesh out with <a href="http://www.squaredroot.com/post/2008/04/OpenID-Check_Authentication.aspx">a security patch</a>. The reason I did so was so that I could include OpenID in this release of the Starter Kit.</p>
<p>Out of the box you can create a route to the OpenIDLogin action, which displays the following view:</p>
<p><a href="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/OpenID_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/OpenID_thumb.jpg" border="0" alt="OpenID" width="204" height="210" /></a></p>
<p>Once the user has entered their OpenID url, the starter kit will take care of the rest for you, with one critical exception: you have to map the url to a user in your membership database. To do so, you simple override a virtual method and return a MembershipUser, like so:</p>
<div class="csharpcode-wrapper">
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:</span> <span class="kwrd">protected</span> <span class="kwrd">override</span> MembershipUser AssociateOpenIDToMembershipUser( <span class="kwrd">string</span> identity, <span class="kwrd">string</span> name, <span class="kwrd">string</span> email )</pre>
<pre class="alteven"><span class="lnum">   2:</span> {</pre>
<pre class="alt"><span class="lnum">   3:</span>     <span class="kwrd">return</span> Membership.GetUser(identity);</pre>
<pre class="alteven"><span class="lnum">   4:</span> }</pre>
</div>
</div>
<p>Note that the above implementation maps the OpenID url to a user&#8217;s UserName, which may or may not be what you want for your application. Adjust accordingly.</p>
<h3>Password Recovery Tools</h3>
<p>Maarten did a great job providing users with a way to manage their passwords. While logged in they can change their password:</p>
<p><a href="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/ChangePassword_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/ChangePassword_thumb.jpg" border="0" alt="ChangePassword" width="167" height="240" /></a></p>
<p>Or if they are having trouble logging in, they can submit their username&#8230;</p>
<p><a href="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/ForgotPassword_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/ForgotPassword_thumb.jpg" border="0" alt="ForgotPassword" width="240" height="184" /></a></p>
<p>&#8230;and then answer their password question (if the system is configured to require it)&#8230;</p>
<p><a href="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/PasswordQuestion_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/PasswordQuestion_thumb.jpg" border="0" alt="PasswordQuestion" width="240" height="177" /></a></p>
<p>&#8230;and they will then receive their password via email (or a newly generated password &#8212; depending on system configuration).</p>
<h3>Client-Side Validation</h3>
<p>All non-administrative forms now include basic client-side validation. The validations even change based upon your Membership settings.</p>
<p>For instance, by default the ASP.Net Membership provider requires passwords to contain at least 1 non-alphanumeric character. If a user entered a password of &#8220;password&#8221; they would see the following alert:</p>
<p><a href="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/ClientSideValidation_2.jpg"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" src="http://www.squaredroot.com/image.axd?picture=WindowsLiveWriter/MVCNewMembershipStarterKitRelease_A490/ClientSideValidation_thumb.jpg" border="0" alt="ClientSideValidation" width="443" height="149" /></a></p>
<h3>Components: Login &amp; LoginStatus</h3>
<p>Maarten created components that emulate the functionality of the old Login and LoginStatus controls. Now it is easy to have a Login box on every page.</p>
<h3>Major Refactoring</h3>
<p>Most of the controller and filter code has been broken out into a separate assembly.</p>
<p>Your FormsAuthentication and FormsAuthenticationAdministration controllers should now inherit from a base version of each. Maarten has created a boat load of virtual method hooks for each action (OnBeforeBlah, OnAfterBlah, OnErrorBlah) that provides you with easy extensibility points without needing to directly modify the starter kit base code.</p>
<p>Hopefully this refactoring will make it easy for you to upgrade to future versions of the starter kit&#8217;s code as they become available.</p>
<h2>The Future</h2>
<p>Currently we&#8217;ve cleared our plate and have no more planned features to attend to. Does this mean that we are done? No. This is what you can expect to see us working on next:</p>
<ul>
<li>Preview3 updates, whenever it becomes available.</li>
<li>Validations on the administrative side.</li>
<li>Bug fixes, of course. <img src='http://www.squaredroot.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>If you have suggestions for what you would like to see in the next release, please <a href="http://www.squaredroot.com/page/About-Me.aspx#ContactInformation">drop me a line</a> and let me know!</li>
</ul>
<p>You can <a href="https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=MvcMembership&amp;ReleaseId=12261">download the new release</a> from CodePlex. </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/04/11/mvc-membership-starter-kit-11/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>MVC: Membership Starter Kit</title>
		<link>http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/</link>
		<comments>http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/#comments</comments>
		<pubDate>Wed, 02 Apr 2008 22:43:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2008/04/02/MVC-Membership-Starter-Kit.aspx</guid>
		<description><![CDATA[A newer version of the Membership Starter Kit is now available. Click here to see what has changed. Introduction One of my very first blog posts (and most definitely my most popular so far) revolved around how to integrate ASP.Net membership and forms authentication into the ASP.Net MVC framework which had just been released in [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>A newer version of the Membership Starter Kit is now available. <a href="http://www.squaredroot.com/post/2008/04/MVC-Membership-Starter-Kit-11.aspx">Click here</a> to see what has changed.</p></blockquote>
<h2>Introduction</h2>
<p>One of my very first blog posts (and most definitely my most popular so far) revolved around <a href="/post/2007/12/ASPNet-MVC-Membership-Basics.aspx">how to integrate ASP.Net membership and forms authentication into the ASP.Net MVC framework</a> which had just been released in it&#8217;s December CTP flavor. It has remained popular to this day, but unfortunately the Preview 2 release of the MVC framework has caused much of the code I released in that article to no longer function correctly.</p>
<p>Even before the release of Preview 2, I had been planning to extend the samples I was providing to offer more useful features. I don&#8217;t know about you, but nearly every website I ever create with ASP.Net requires some kind of security/membership system. My preference is to use the built-in system when possible (except for the horrible Profiles sub-system). This means creating login, logout, &amp; registration functionality every time, as well as creating administrative screens for managing the users that enter your system.</p>
<p>WebForms provides some controls to help with the login and registration process, but user administration has always been delegated to either (a) the built-in tool that runs separately and doesn&#8217;t work remotely or (b) rolling your own solution. The development of the MVC framework seems to me like a good time to resolve this scenario and provide the community with an array of pre-built tools to help boot-strap projects so that we can stop working on infrastructure and start working on the heart of the individual application.</p>
<p><strong>With that in mind I have created a CodePlex project: the </strong><a href="http://www.codeplex.com/MvcMembership"><strong>ASP.Net MVC Membership Starter Kit</strong></a><strong>.</strong> It currently provides controllers and views for all of the common authentication and user administration needs, including:</p>
<ul>
<li>Login/Logout</li>
<li>Registration</li>
<li>List of Registered Users</li>
<li>User Details / Administration</li>
<li>Role Management</li>
</ul>
<p>A big thanks goes out to Rob Conery, as I borrowed his recent <a href="http://blog.wekeroad.com/blog/aspnet-mvc-securing-your-controller-actions/">Authentication Filters</a> and included those, along with my recently released <a href="/post/2008/04/MVC-Error-Handler-Filter.aspx">Error Handling Filters</a>.</p>
<p>Okay, enough wall o&#8217;text. Let&#8217;s take a look at some screenshots:</p>
<h2>Screenshot Tour</h2>
<p>Here is the menu when you first log in:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Menu-LoggedOut_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Menu-LoggedOut_thumb.jpg" border="0" alt="Menu-LoggedOut" width="377" height="72" /></a></p>
<p>The registration page:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Registration_4.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Registration_thumb_1.jpg" border="0" alt="Registration" width="219" height="240" /></a></p>
<p>The login page (note that the Administrator&#8217;s credentials are displayed to make it easy to get started, you&#8217;ll obviously want to change them and remove that note):</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Login_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Login_thumb.jpg" border="0" alt="Login" width="240" height="216" /></a></p>
<p>Having logged in, here is what the menu looks like now:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Menu-LoggedIn_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Menu-LoggedIn_thumb.jpg" border="0" alt="Menu-LoggedIn" width="380" height="68" /></a></p>
<p>The current options upon clicking the Security tab:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Security_2.jpg"><img src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Security_thumb.jpg" border="0" alt="Security" width="147" height="157" /></a></p>
<p>Clicking &#8220;Manage Users&#8221; brings you to a list of all users currently registered:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/ManageUsers_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/ManageUsers_thumb.jpg" border="0" alt="ManageUsers" width="171" height="105" /></a></p>
<p>Clicking on the user takes you to a form that allows you to view their details and edit a few aspects of their profile&#8230;</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/User-Top_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/User-Top_thumb.jpg" border="0" alt="User-Top" width="196" height="240" /></a></p>
<p>as well as view/change the roles they are in and help with password issues:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/User-Bottom_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/User-Bottom_thumb.jpg" border="0" alt="User-Bottom" width="182" height="240" /></a></p>
<p>From the Security tab you can also go to a list of all the system&#8217;s roles, from which you can add/delete roles as you need:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Roles_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/Roles_thumb.jpg" border="0" alt="Roles" width="426" height="264" /></a></p>
<p>Clicking on a role from the roles list or the user profile allows you to view/modify the users in that role:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/UsersInRole_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/UsersInRole_thumb.jpg" border="0" alt="UsersInRole" width="428" height="147" /></a></p>
<p>And finally, the Security tab offers a link to another registration form, geared toward Administrators:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/CreateUser_2.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="/image.axd?picture=WindowsLiveWriter/MVCMembershipStarterKit_F5A6/CreateUser_thumb.jpg" border="0" alt="CreateUser" width="230" height="240" /></a></p>
<h2>NSFAQ (Not-So Frequently Asked Questions)</h2>
<p><strong>Q:</strong> Does this compete with MvcContrib?<br />
<strong>A:</strong> No. <a href="http://www.codeplex.com/MVCContrib">MvcContrib</a> is a great project that aims to features like alternate routing and view engines, and IoC integration. This project is simply a starter kit to help get membership-based applications off the ground a little quicker. There is no reason you could not use both projects together.</p>
<p><strong>Q:</strong> What dependencies does using this starter kit saddle me with?<br />
<strong>A:</strong> Ideally, none, other than the ASP.Net Membership API. Every measure will be taken to avoid using third party libraries, be it JavaScript or .Net. We will strive to separate the code and rely on default settings as much as possible to make it easy for you to customize your installation without anything in the starter kit getting in the way.</p>
<p><strong>Q:</strong> Who is responsible for this?<br />
<strong>A:</strong> Currently, only <a href="/page/About-Me.aspx">me</a>, but I&#8217;d like that to change! I&#8217;m keenly interested in finding a few other developers that would like to contribute to enhancing the starter kit. Please <a href="/page/About-Me.aspx#ContactInformation">contact me</a> if you&#8217;d like to help!</p>
<h2>What&#8217;s Next?</h2>
<p>There are a few features missing that I would like to include in the very short term. Primarily these are features for end-users, like Change Password and Forgot My Password (both of which are currently available on the administration side). Beyond that, visual cleanup of the forms (and separation of the style sheets) as well as a bit of AJAX-ification of the forms would be nice. If you use the starter kit and have suggestions or criticisms, please post to the <a href="http://www.codeplex.com/MvcMembership/Thread/List.aspx">Discussions forum</a> or <a href="http://www.codeplex.com/MvcMembership/WorkItem/List.aspx">Issue Tracker</a>!</p>
<p>You can download the latest release from <a href="http://www.codeplex.com/MvcMembership">the CodePlex project</a>. I hope you all find it useful! </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2008/04/02/mvc-membership-starter-kit/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>ASP.Net MVC Membership Basics</title>
		<link>http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/</link>
		<comments>http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/#comments</comments>
		<pubDate>Mon, 10 Dec 2007 20:26:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[MVC]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[membership]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2007/12/10/ASPNet-MVC-Membership-Basics.aspx</guid>
		<description><![CDATA[NOTE: This article was written for the December CTP release of the MVC framework. Unfortunately, it does not entirely apply to the Preview 2 release or subsequent releases. The MVC bits have finally arrived and I&#8217;ve spent a while digesting them. I&#8217;ve been waiting for the bits to be released to begin working on a [...]]]></description>
			<content:encoded><![CDATA[<blockquote class="warning"><p><b>NOTE</b>:      <br />This article was written for the December CTP release of the MVC framework. Unfortunately, it does not entirely apply to the Preview 2 release or subsequent releases.</p>
</blockquote>
<p><a href="http://asp.net/downloads/3.5-extensions/">The MVC bits have finally arrived</a> and I&#8217;ve spent a while digesting them. I&#8217;ve been waiting for the bits to be released to begin working on a side-project, so the first thing I did after downloading them last night was crank it up and start working on a new ASP.NET MVC Web Application project. </p>
<p>Typically, the first thing I do on a new project is set up the authentication/authorization system. For the project I am working on I want to use the ASP.Net Membership system, but most of the Membership controls do not work with the MVC framework because they require postbacks. I spent some time last night building a Security controller and views for Registration and Login that I thought would be worth sharing. </p>
<p>So far I have implemented basic functionality for Register, Login, and Logout. There are three files we will have to create. We will also have to change the routing table. Let&#8217;s start with the SecurityController: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Courier New;}}{colortbl;??red0green0blue255;red255green255blue255;red0green0blue0;red43green145blue175;red163green21blue21;red0green128blue0;}??fs20 cf1 publiccf0  cf1 classcf0  cf4 SecurityControllercf0  : cf4 Controllerpar ??cf0 {par ??par ??tab [cf4 ControllerActioncf0 ]par ??tab cf1 publiccf0  cf1 voidcf0  Login()par ??tab {par ??tab tab RenderView(cf5 "Login"cf0 );par ??tab }par ??par ??tab [cf4 ControllerActioncf0 ]par ??tab cf1 publiccf0  cf1 voidcf0  Register()par ??tab {par ??tab tab RenderView( cf5 "Register"cf0  );par ??tab }par ??par ??tab [cf4 ControllerActioncf0 ]par ??tab cf1 publiccf0  cf1 voidcf0  Logout()par ??tab {par ??tab tab cf4 FormsAuthenticationcf0 .SignOut();par ??tab tab Response.Redirect( cf5 "/"cf0  );par ??tab }par ??par ??tab [cf4 ControllerActioncf0 ]par ??tab cf1 publiccf0  cf1 voidcf0  Authenticate( cf1 stringcf0  userName, cf1 stringcf0  password, cf1 stringcf0  rememberMe, cf1 stringcf0  returnUrl )par ??tab {par ??tab tab cf6 // figure out if username and password are correctpar ??cf0 tab tab cf1 ifcf0 ( cf4 Membershipcf0 .ValidateUser( userName, password ) )par ??tab tab {par ??tab tab tab cf6 // everything is good, create an authticket and gopar ??cf0 tab tab tab cf4 FormsAuthenticationcf0 .SetAuthCookie( userName, (rememberMe == cf1 nullcf0 ) );par ??tab tab tab Response.Redirect( returnUrl );par ??tab tab }par ??tab tab cf1 elsepar ??cf0 tab tab {par ??tab tab tab cf6 // something was wrong, figure out which and pass it into viewpar ??cf0 tab tab tab cf1 ifcf0 ( cf4 Membershipcf0 .GetUser(userName) == cf1 nullcf0  )par ??tab tab tab tab ViewData[cf5 "ErrorMessage"cf0 ] = cf5 "Incorrect username."cf0 ;par ??tab tab tab cf1 elsepar ??cf0 tab tab tab tab ViewData[cf5 "ErrorMessage"cf0 ] = cf5 "Incorrect password."cf0 ;par ??tab tab tab RenderView( cf5 "Login"cf0  );par ??tab tab }par ??tab }par ??par ??tab [cf4 ControllerActioncf0 ]par ??tab cf1 publiccf0  cf1 voidcf0  CreateUser( cf1 stringcf0  userName, cf1 stringcf0  emailAddress, cf1 stringcf0  password, cf1 stringcf0  returnUrl )par ??tab {par ??tab tab cf1 trypar ??cf0 tab tab {par ??tab tab tab cf6 // try to create user and then login that userpar ??cf0 tab tab tab cf1 ifcf0 ( cf4 Membershipcf0 .CreateUser( userName, password, emailAddress ) == cf1 nullcf0  )par ??tab tab tab tab cf1 throwcf0  cf1 newcf0  cf4 MembershipCreateUserExceptioncf0 ( cf5 "An unspecified error occurred."cf0  );par ??tab tab tab cf4 FormsAuthenticationcf0 .SetAuthCookie( userName, cf1 truecf0  );par ??tab tab tab Response.Redirect( returnUrl );par ??tab tab }par ??tab tab cf1 catchcf0 ( cf4 MembershipCreateUserExceptioncf0  e )par ??tab tab {par ??tab tab tab cf6 // something went wrong, pass the message down to the viewpar ??cf0 tab tab tab ViewData[cf5 "ErrorMessage"cf0 ] = e.Message;par ??tab tab tab RenderView(cf5 "Register"cf0 );par ??tab tab tab cf1 returncf0 ;par ??tab tab }par ??tab }par ??par ??}}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: blue">public</span> <span style="color: blue">class</span> <span style="color: #2b91af">SecurityController</span> : <span style="color: #2b91af">Controller</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span> { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160;&#160;&#160;&#160; [<span style="color: #2b91af">ControllerAction</span>] </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;&#160;&#160;&#160; <span style="color: blue">public</span> <span style="color: blue">void</span> Login() </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 7</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RenderView(<span style="color: #a31515">&quot;Login&quot;</span>); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 8</span>&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 9</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 10</span>&#160;&#160;&#160;&#160; [<span style="color: #2b91af">ControllerAction</span>] </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 11</span>&#160;&#160;&#160;&#160; <span style="color: blue">public</span> <span style="color: blue">void</span> Register() </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 12</span>&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 13</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RenderView( <span style="color: #a31515">&quot;Register&quot;</span> ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 14</span>&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 15</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 16</span>&#160;&#160;&#160;&#160; [<span style="color: #2b91af">ControllerAction</span>] </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 17</span>&#160;&#160;&#160;&#160; <span style="color: blue">public</span> <span style="color: blue">void</span> Logout() </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 18</span>&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 19</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #2b91af">FormsAuthentication</span>.SignOut(); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 20</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Response.Redirect( <span style="color: #a31515">&quot;/&quot;</span> ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 21</span>&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 22</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 23</span>&#160;&#160;&#160;&#160; [<span style="color: #2b91af">ControllerAction</span>] </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 24</span>&#160;&#160;&#160;&#160; <span style="color: blue">public</span> <span style="color: blue">void</span> Authenticate( <span style="color: blue">string</span> userName, <span style="color: blue">string</span> password, <span style="color: blue">string</span> rememberMe, <span style="color: blue">string</span> returnUrl ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 25</span>&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 26</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: green">// figure out if username and password are correct</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 27</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">if</span>( <span style="color: #2b91af">Membership</span>.ValidateUser( userName, password ) ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 28</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 29</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: green">// everything is good, create an authticket and go</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 30</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #2b91af">FormsAuthentication</span>.SetAuthCookie( userName, (rememberMe != <span style="color: blue">null</span>) ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 31</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Response.Redirect( returnUrl ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 32</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 33</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">else</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 34</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 35</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: green">// something was wrong, figure out which and pass it into view</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 36</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">if</span>( <span style="color: #2b91af">Membership</span>.GetUser(userName) == <span style="color: blue">null</span> ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 37</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] = <span style="color: #a31515">&quot;Incorrect username.&quot;</span>; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 38</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">else</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 39</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] = <span style="color: #a31515">&quot;Incorrect password.&quot;</span>; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 40</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RenderView( <span style="color: #a31515">&quot;Login&quot;</span> ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 41</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 42</span>&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 43</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 44</span>&#160;&#160;&#160;&#160; [<span style="color: #2b91af">ControllerAction</span>] </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 45</span>&#160;&#160;&#160;&#160; <span style="color: blue">public</span> <span style="color: blue">void</span> CreateUser( <span style="color: blue">string</span> userName, <span style="color: blue">string</span> emailAddress, <span style="color: blue">string</span> password, <span style="color: blue">string</span> returnUrl ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 46</span>&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 47</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">try</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 48</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 49</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: green">// try to create user and then login that user</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 50</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">if</span>( <span style="color: #2b91af">Membership</span>.CreateUser( userName, password, emailAddress ) == <span style="color: blue">null</span> ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 51</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">throw</span> <span style="color: blue">new</span> <span style="color: #2b91af">MembershipCreateUserException</span>( <span style="color: #a31515">&quot;An unspecified error occurred.&quot;</span> ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 52</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #2b91af">FormsAuthentication</span>.SetAuthCookie( userName, <span style="color: blue">true</span> ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 53</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Response.Redirect( returnUrl ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 54</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 55</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">catch</span>( <span style="color: #2b91af">MembershipCreateUserException</span> e ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 56</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 57</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: green">// something went wrong</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 58</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] = e.Message; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 59</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RenderView(<span style="color: #a31515">&quot;Register&quot;</span>); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 60</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">return</span>; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 61</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 62</span>&#160;&#160;&#160;&#160; } </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 63</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 64</span> } </p>
</p></div>
<p>&#160; </p>
<p>So we have two basic actions methods that only display views (Register and Login) and three action-only methods that have no views (CreateUser, Authenticate, Logout). </p>
<p>I have chosen to not have a logout page, but to instead redirect to the homepage. Switch out &#8216;Response.Redirect( <span style="color: #a31515">&quot;/&quot;</span> );&#8217; for &#8216;RenderView( &quot;Logout&quot; );&#8217; and create a Logout.aspx view if you would like to display a logout message. </p>
<p>Now let&#8217;s look at the Login view: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Courier New;}}{colortbl;??red0green0blue255;red255green255blue255;red163green21blue21;red0green0blue0;red255green0blue0;red255green238blue98;}??fs20 cf1 &lt;cf3 aspcf1 :cf3 Contentcf0  cf5 IDcf1 ="content"cf0  cf5 ContentPlaceHolderIDcf1 ="MainContentPlaceHolder"cf0  cf5 runatcf1 ="server"&gt;par ??par ??cf0 tab cf1 &lt;cf3 h2cf1 &gt;cf0 Logincf1 &lt;/cf3 h2cf1 &gt;par ??par ??cf0 tab cb6highlight6 &lt;%cb0highlight0  cf1 ifcf0 ( ViewData[cf3 "ErrorMessage"cf0 ] != cf1 nullcf0  ){ cb6highlight6 %&gt;par ??cb0highlight0 tab cf1 &lt;cf3 pcf1 &gt;cf0cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 ViewData[cf3 "ErrorMessage"cf0 ] cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 pcf1 &gt;par ??cf0 tab cb6highlight6 &lt;%cb0highlight0  } cb6highlight6 %&gt;par ??par ??cb0highlight0 tab cb6highlight6 &lt;%cb0highlight0  cf1 usingcf0 (Html.Form( cf3 "Authenticate"cf0 , cf3 "Security"cf0  )){ cb6highlight6 %&gt;par ??cb0highlight0 tab cf1 &lt;cf3 fieldsetcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 legendcf1 &gt;cf0 Logincf1 &lt;/cf3 legendcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;&lt;cf3 labelcf0  cf5 forcf1 ="userName"&gt;cf0 User Name:cf1 &lt;/cf3 labelcf1 &gt;cf0  cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.TextBox( cf3 "userName"cf0  ) cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;&lt;cf3 labelcf0  cf5 forcf1 ="password"&gt;cf0 Password:cf1 &lt;/cf3 labelcf1 &gt;cf0  cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.Password( cf3 "password"cf0  ) cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;&lt;cf3 labelcf0  cf5 forcf1 ="password"cf0  cf5 onclickcf1 ="document.getElementById('rememberMe').checked = !document.getElementById('rememberMe').checked;"&gt;cf0 Remember Me:cf1 &lt;/cf3 labelcf1 &gt;par ??cf0 tab tab tab cf1 &lt;cf3 inputcf0  cf5 typecf1 ="checkbox"cf0  cf5 idcf1 ="rememberMe"cf0  cf5 namecf1 ="rememberMe"cf0  cf5 checkedcf1 ="checked"cf0  cf5 valuecf1 ="checked"cf0  cf1 /&gt;&lt;/cf3 divcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;cf0cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.SubmitButton() cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.Hidden( cf3 "returnUrl"cf0 , cf3 "/"cf0  ) cb6highlight6 %&gt;par ??cb0highlight0 tab cf1 &lt;/cf3 fieldsetcf1 &gt;par ??cf0 tab cb6highlight6 &lt;%cb0highlight0  } cb6highlight6 %&gt;par ??par ??cf1cb0highlight0 &lt;/cf3 aspcf1 :cf3 Contentcf1 &gt;}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span> <span style="color: red">ID</span><span style="color: blue">=&quot;content&quot;</span> <span style="color: red">ContentPlaceHolderID</span><span style="color: blue">=&quot;MainContentPlaceHolder&quot;</span> <span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">h2</span><span style="color: blue">&gt;</span>Login<span style="color: blue">&lt;/</span><span style="color: #a31515">h2</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> <span style="color: blue">if</span>( ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] != <span style="color: blue">null</span> ){ <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span><span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 7</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> } <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 8</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 9</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> <span style="color: blue">using</span>(Html.Form( <span style="color: #a31515">&quot;Authenticate&quot;</span>, <span style="color: #a31515">&quot;Security&quot;</span> )){ <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 10</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">fieldset</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 11</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">legend</span><span style="color: blue">&gt;</span>Login<span style="color: blue">&lt;/</span><span style="color: #a31515">legend</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 12</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;&lt;</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=&quot;userName&quot;&gt;</span>User Name:<span style="color: blue">&lt;/</span><span style="color: #a31515">label</span><span style="color: blue">&gt;</span> <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.TextBox( <span style="color: #a31515">&quot;userName&quot;</span> ) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 13</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;&lt;</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=&quot;password&quot;&gt;</span>Password:<span style="color: blue">&lt;/</span><span style="color: #a31515">label</span><span style="color: blue">&gt;</span> <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.Password( <span style="color: #a31515">&quot;password&quot;</span> ) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 14</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;&lt;</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=&quot;rememberMe&quot;</span><span style="color: blue">&gt;</span>Remember Me:<span style="color: blue">&lt;/</span><span style="color: #a31515">label</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 15</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">input</span> <span style="color: red">type</span><span style="color: blue">=&quot;checkbox&quot;</span> <span style="color: red">id</span><span style="color: blue">=&quot;rememberMe&quot;</span> <span style="color: red">name</span><span style="color: blue">=&quot;rememberMe&quot;</span> <span style="color: red">checked</span><span style="color: blue">=&quot;checked&quot;</span> <span style="color: red">value</span><span style="color: blue">=&quot;checked&quot;</span> <span style="color: blue">/&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 16</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span><span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.SubmitButton() <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 17</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.Hidden( <span style="color: #a31515">&quot;returnUrl&quot;</span>, <span style="color: #a31515">&quot;/&quot;</span> ) <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 18</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;/</span><span style="color: #a31515">fieldset</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 19</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> } <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 20</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 21</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;</span> </p>
</p></div>
<p>&#160; </p>
<p>The toolkit&#8217;s Html.Checkbox(&#8230;) method annoys me. More on why in another post. For now I&#8217;ve instead just written the html out by hand. You&#8217;ll note I&#8217;ve also linked the label to the checkbox with JavaScript so that clicking the label toggles the checkbox. </p>
<p>Then the Register view: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Courier New;}}{colortbl;??red0green0blue255;red255green255blue255;red163green21blue21;red0green0blue0;red255green0blue0;red255green238blue98;}??fs20 cf1 &lt;cf3 aspcf1 :cf3 Contentcf0  cf5 IDcf1 ="content"cf0  cf5 ContentPlaceHolderIDcf1 ="MainContentPlaceHolder"cf0  cf5 runatcf1 ="server"&gt;par ??par ??cf0 tab cf1 &lt;cf3 h2cf1 &gt;cf0 Registercf1 &lt;/cf3 h2cf1 &gt;par ??par ??cf0 tab cb6highlight6 &lt;%cb0highlight0  cf1 ifcf0 ( ViewData[cf3 "ErrorMessage"cf0 ] != cf1 nullcf0  ){ cb6highlight6 %&gt;par ??cb0highlight0 tab cf1 &lt;cf3 pcf1 &gt;cf0cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 ViewData[cf3 "ErrorMessage"cf0 ] cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 pcf1 &gt;par ??cf0 tab cb6highlight6 &lt;%cb0highlight0  } cb6highlight6 %&gt;par ??par ??cb0highlight0 tab cb6highlight6 &lt;%cb0highlight0  cf1 usingcf0 (Html.Form( cf3 "CreateUser"cf0 , cf3 "Security"cf0  )){ cb6highlight6 %&gt;par ??cb0highlight0 tab cf1 &lt;cf3 fieldsetcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 legendcf1 &gt;cf0 Registercf1 &lt;/cf3 legendcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;&lt;cf3 labelcf0  cf5 forcf1 ="userName"&gt;cf0 User Name:cf1 &lt;/cf3 labelcf1 &gt;cf0  cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.TextBox( cf3 "userName"cf0  ) cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;&lt;cf3 labelcf0  cf5 forcf1 ="emailAddress"&gt;cf0 Email Address:cf1 &lt;/cf3 labelcf1 &gt;cf0  cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.TextBox( cf3 "emailAddress"cf0  ) cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;&lt;cf3 labelcf0  cf5 forcf1 ="password"&gt;cf0 Password:cf1 &lt;/cf3 labelcf1 &gt;cf0  cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.Password( cf3 "password"cf0  ) cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cf1 &lt;cf3 divcf1 &gt;cf0cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.SubmitButton() cb6highlight6 %&gt;cf1cb0highlight0 &lt;/cf3 divcf1 &gt;par ??cf0 tab tab cb6highlight6 &lt;%cb0highlight0  cf1 =cf0 Html.Hidden( cf3 "returnUrl"cf0 , cf3 "/"cf0  ) cb6highlight6 %&gt;par ??cb0highlight0 tab cf1 &lt;/cf3 fieldsetcf1 &gt;par ??cf0 tab cb6highlight6 &lt;%cb0highlight0  } cb6highlight6 %&gt;par ??par ??cf1cb0highlight0 &lt;/cf3 aspcf1 :cf3 Contentcf1 &gt;}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span> <span style="color: red">ID</span><span style="color: blue">=&quot;content&quot;</span> <span style="color: red">ContentPlaceHolderID</span><span style="color: blue">=&quot;MainContentPlaceHolder&quot;</span> <span style="color: red">runat</span><span style="color: blue">=&quot;server&quot;&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">h2</span><span style="color: blue">&gt;</span>Register<span style="color: blue">&lt;/</span><span style="color: #a31515">h2</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> <span style="color: blue">if</span>( ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] != <span style="color: blue">null</span> ){ <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span><span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>ViewData[<span style="color: #a31515">&quot;ErrorMessage&quot;</span>] <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">p</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 7</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> } <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 8</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 9</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> <span style="color: blue">using</span>(Html.Form( <span style="color: #a31515">&quot;CreateUser&quot;</span>, <span style="color: #a31515">&quot;Security&quot;</span> )){ <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 10</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">fieldset</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 11</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">legend</span><span style="color: blue">&gt;</span>Register<span style="color: blue">&lt;/</span><span style="color: #a31515">legend</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 12</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;&lt;</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=&quot;userName&quot;&gt;</span>User Name:<span style="color: blue">&lt;/</span><span style="color: #a31515">label</span><span style="color: blue">&gt;</span> <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.TextBox( <span style="color: #a31515">&quot;userName&quot;</span> ) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 13</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;&lt;</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=&quot;emailAddress&quot;&gt;</span>Email Address:<span style="color: blue">&lt;/</span><span style="color: #a31515">label</span><span style="color: blue">&gt;</span> <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.TextBox( <span style="color: #a31515">&quot;emailAddress&quot;</span> ) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 14</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;&lt;</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=&quot;password&quot;&gt;</span>Password:<span style="color: blue">&lt;/</span><span style="color: #a31515">label</span><span style="color: blue">&gt;</span> <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.Password( <span style="color: #a31515">&quot;password&quot;</span> ) <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 15</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: blue">&lt;</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span><span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.SubmitButton() <span style="background: #ffee62">%&gt;</span><span style="color: blue">&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 16</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> <span style="color: blue">=</span>Html.Hidden( <span style="color: #a31515">&quot;returnUrl&quot;</span>, <span style="color: #a31515">&quot;/&quot;</span> ) <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 17</span>&#160;&#160;&#160;&#160; <span style="color: blue">&lt;/</span><span style="color: #a31515">fieldset</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 18</span>&#160;&#160;&#160;&#160; <span style="background: #ffee62">&lt;%</span> } <span style="background: #ffee62">%&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 19</span>&#160; </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 20</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">asp</span><span style="color: blue">:</span><span style="color: #a31515">Content</span><span style="color: blue">&gt;</span> </p>
</p></div>
<p>&#160; </p>
<p>Another straightforward view. Not much to discuss here. </p>
<p>And finally, let&#8217;s add the new routes: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Courier New;}}{colortbl;??red43green145blue175;red255green255blue255;red0green0blue0;red0green0blue255;red163green21blue21;}??fs20 cf1 RouteTablecf0 .Routes.Add( cf4 newcf0  cf1 Routepar ??cf0 {par ??tab Url = cf5 "Login"cf0 ,par ??tab Defaults = cf4 newcf0  {par ??tab tab controller = cf5 "Security"cf0 ,par ??tab tab action = cf5 "Register"cf0  },par ??tab RouteHandler = cf4 typeofcf0 ( cf1 MvcRouteHandlercf0  )par ??} );par ??cf1 RouteTablecf0 .Routes.Add( cf4 newcf0  cf1 Routepar ??cf0 {par ??tab Url = cf5 "Register"cf0 ,par ??tab Defaults = cf4 newcf0  {par ??tab tab controller = cf5 "Security"cf0 ,par ??tab tab action = cf5 "Register"cf0  },par ??tab RouteHandler = cf4 typeofcf0 ( cf1 MvcRouteHandlercf0  )par ??} );}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: #2b91af">RouteTable</span>.Routes.Add( <span style="color: blue">new</span> <span style="color: #2b91af">Route</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span> { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160;&#160;&#160;&#160; Url = <span style="color: #a31515">&quot;Login&quot;</span>, </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160;&#160;&#160;&#160; Defaults = <span style="color: blue">new</span> { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; controller = <span style="color: #a31515">&quot;Security&quot;</span>, </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; action = <span style="color: #a31515">&quot;Login&quot;</span> }, </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 7</span>&#160;&#160;&#160;&#160; RouteHandler = <span style="color: blue">typeof</span>( <span style="color: #2b91af">MvcRouteHandler</span> ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 8</span> } ); </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 9</span>&#160;<span style="color: #2b91af">RouteTable</span>.Routes.Add( <span style="color: blue">new</span> <span style="color: #2b91af">Route</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 10</span> { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 11</span>&#160;&#160;&#160;&#160; Url = <span style="color: #a31515">&quot;Register&quot;</span>, </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 12</span>&#160;&#160;&#160;&#160; Defaults = <span style="color: blue">new</span> { </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 13</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; controller = <span style="color: #a31515">&quot;Security&quot;</span>, </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 14</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; action = <span style="color: #a31515">&quot;Register&quot;</span> }, </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 15</span>&#160;&#160;&#160;&#160; RouteHandler = <span style="color: blue">typeof</span>( <span style="color: #2b91af">MvcRouteHandler</span> ) </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 16</span> } ); </p>
</p></div>
<p>&#160; </p>
<p>I personally like login to be <a href="http://website/login">http://website/login</a> and register to be <a href="http://website/register">http://website/register</a>, so that is how I have configured it. The other three actions (Logout, Authenticate, and CreateUser) I access via the default route (ex: /Security/Logout). </p>
<p>That&#8217;s it! You should now have a working registration/login system. I&#8217;ll leave making it pretty with CSS as an exercise for the reader. </p>
<p>I have included all of the code samples above in the below ZIP file. Just unzip it and place the controller into the Controllers directory, the views into the Views/Security directory (which you will have to create), and copy the code from Routes.txt to the appropriate area of your Global.asax. </p>
<p><a href="/file.axd?file=MVCMembership_v1.2.zip" rel="enclosure">MVCMembership_v1.2.zip (2.03 kb)</a> </p>
<p><strong>UPDATE (Dec 11):</strong> Johan and <a href="http://stevenharman.net/">Steve Harman</a> were kind enough to <a href="/post/2007/12/ASPNet-MVC-Membership-Basics.aspx#Comment64151417-6f79-472c-83a7-2db37cbbb73a">point out</a> that I had foolishly set the &quot;remember me&quot; checkbox&#8217;s label&#8217;s &quot;for&quot; attribute to point to the password field instead of the checkbox itself. I have fixed the code above and provided a new zip file (1.1) for download. Thanks guys! </p>
<p><strong>Update (Dec 19):</strong> <a href="http://www.superwasp.net/weblog/">oVan</a> <a href="/post/2007/12/ASPNet-MVC-Membership-Basics.aspx#Comment76caa980-70fe-4d9e-b1c5-a7f75e43de3d">pointed out a bug</a> in the routing rules defined in the routes.txt file. I have updated the zip file with the correct code. Thanks oVan! </p>
<p><strong>Update (Jan 3):</strong> <a href="/post/2007/12/ASPNet-MVC-Membership-Basics.aspx#Comment84f3301f-4a3f-408d-b472-ae81cbcb6ad1">James Nail asked a very good question via a comment</a>: what do you set for the loginUrl and defaultUrl in your web.config? Well James, here is how I&#8217;ve setup my web.config&#8230; </p>
<p>Assuming we&#8217;ll be using forms authentication and securing all pages except login and the homepage, place the following inside the &lt;system.web&gt;element: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red0green0blue255;red255green255blue255;red163green21blue21;red255green0blue0;red0green0blue0;}??fs18 cf1 &lt;cf3 authenticationcf1  cf4 modecf1 =cf0 "cf1 Formscf0 "cf1 &gt;par ??tab &lt;cf3 formscf1  cf4 loginUrlcf1 =cf0 "cf1 /Logincf0 "cf1  cf4 defaultUrlcf1 =cf0 "cf1 /cf0 "cf1  /&gt;par ??&lt;/cf3 authenticationcf1 &gt;par ??&lt;cf3 authorizationcf1 &gt;par ??tab &lt;cf3 denycf1  cf4 userscf1 =cf0 "cf1 ?cf0 "cf1  /&gt;par ??&lt;/cf3 authorizationcf1 &gt;}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">authentication</span><span style="color: blue"> </span><span style="color: red">mode</span><span style="color: blue">=</span>&quot;<span style="color: blue">Forms</span>&quot;<span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span>&#160;<span style="color: blue">&#160; &lt;</span><span style="color: #a31515">forms</span><span style="color: blue"> </span><span style="color: red">loginUrl</span><span style="color: blue">=</span>&quot;<span style="color: blue">/Login</span>&quot;<span style="color: blue"> </span><span style="color: red">defaultUrl</span><span style="color: blue">=</span>&quot;<span style="color: blue">/</span>&quot;<span style="color: blue"> /&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">authentication</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;<span style="color: blue">&#160; &lt;</span><span style="color: #a31515">deny</span><span style="color: blue"> </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">?</span>&quot;<span style="color: blue"> /&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
</p></div>
<p>Then, somewhere outside the &lt;system.web&gt; element add: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red0green0blue255;red255green255blue255;red163green21blue21;red255green0blue0;red0green0blue0;}??fs18 cf1 tab &lt;cf3 locationcf1  cf4 pathcf1 =cf0 "cf1 Default.aspxcf0 "cf1 &gt;par ??tab tab &lt;cf3 system.webcf1 &gt;par ??tab tab tab &lt;cf3 authorizationcf1 &gt;par ??tab tab tab tab &lt;cf3 allowcf1  cf4 userscf1 =cf0 "cf1 *cf0 "cf1  /&gt;par ??tab tab tab &lt;/cf3 authorizationcf1 &gt;par ??tab tab &lt;/cf3 system.webcf1 &gt;par ??tab &lt;/cf3 locationcf1 &gt;par ??tab &lt;cf3 locationcf1  cf4 pathcf1 =cf0 "cf1 Security/Authenticatecf0 "cf1 &gt;par ??tab tab &lt;cf3 system.webcf1 &gt;par ??tab tab tab &lt;cf3 authorizationcf1 &gt;par ??tab tab tab tab &lt;cf3 allowcf1  cf4 userscf1 =cf0 "cf1 *cf0 "cf1  /&gt;par ??tab tab tab &lt;/cf3 authorizationcf1 &gt;par ??tab tab &lt;/cf3 system.webcf1 &gt;par ??tab &lt;/cf3 locationcf1 &gt;par ??tab &lt;cf3 locationcf1  cf4 pathcf1 =cf0 "cf1 Logincf0 "cf1 &gt;par ??tab tab &lt;cf3 system.webcf1 &gt;par ??tab tab tab &lt;cf3 authorizationcf1 &gt;par ??tab tab tab tab &lt;cf3 allowcf1  cf4 userscf1 =cf0 "cf1 *cf0 "cf1  /&gt;par ??tab tab tab &lt;/cf3 authorizationcf1 &gt;par ??tab tab &lt;/cf3 system.webcf1 &gt;par ??tab &lt;/cf3 locationcf1 &gt;}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">location</span><span style="color: blue"> </span><span style="color: red">path</span><span style="color: blue">=</span>&quot;<span style="color: blue">Default.aspx</span>&quot;<span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span>&#160;<span style="color: blue">&#160; &lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160;<span style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span style="color: #a31515">allow</span><span style="color: blue"> </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;<span style="color: blue"> /&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;/</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;<span style="color: blue">&#160; &lt;/</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 7</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">location</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 8</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">location</span><span style="color: blue"> </span><span style="color: red">path</span><span style="color: blue">=</span>&quot;<span style="color: blue">Security</span>&quot;<span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 9</span>&#160;<span style="color: blue">&#160; &lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 10</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 11</span>&#160;<span style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span style="color: #a31515">allow</span><span style="color: blue"> </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;<span style="color: blue"> /&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 12</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;/</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 13</span>&#160;<span style="color: blue">&#160; &lt;/</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 14</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">location</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 15</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">location</span><span style="color: blue"> </span><span style="color: red">path</span><span style="color: blue">=</span>&quot;<span style="color: blue">Login</span>&quot;<span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 16</span>&#160;<span style="color: blue">&#160; &lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 17</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 18</span>&#160;<span style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span style="color: #a31515">allow</span><span style="color: blue"> </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;<span style="color: blue"> /&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 19</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;/</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 20</span>&#160;<span style="color: blue">&#160; &lt;/</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160; 21</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">location</span><span style="color: blue">&gt;</span> </p>
</p></div>
<p>Note that this will grant access to all actions within the Security controller. It is also worth pointing out that, dependent on your setup, your CSS and image files may not load unless you also create a location path for their directory and grant all users access like so: </p>
<p> <!--<br />
{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red0green0blue255;red255green255blue255;red163green21blue21;red255green0blue0;red0green0blue0;}??fs18 cf1 tab &lt;cf3 locationcf1  cf4 pathcf1 =cf0 "cf1 Contentcf0 "cf1 &gt;par ??tab tab &lt;cf3 system.webcf1 &gt;par ??tab tab tab &lt;cf3 authorizationcf1 &gt;par ??tab tab tab tab &lt;cf3 allowcf1  cf4 userscf1 =cf0 "cf1 *cf0 "cf1  /&gt;par ??tab tab tab &lt;/cf3 authorizationcf1 &gt;par ??tab tab &lt;/cf3 system.webcf1 &gt;par ??tab &lt;/cf3 locationcf1 &gt;}<br />
-->
<div style="font-size: 9pt; background: white; color: black; font-family: courier new">
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 1</span>&#160;<span style="color: blue">&lt;</span><span style="color: #a31515">location</span><span style="color: blue"> </span><span style="color: red">path</span><span style="color: blue">=</span>&quot;<span style="color: blue">Content</span>&quot;<span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 2</span>&#160;<span style="color: blue">&#160; &lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 3</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 4</span>&#160;<span style="color: blue">&#160;&#160;&#160;&#160;&#160; &lt;</span><span style="color: #a31515">allow</span><span style="color: blue"> </span><span style="color: red">users</span><span style="color: blue">=</span>&quot;<span style="color: blue">*</span>&quot;<span style="color: blue"> /&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 5</span>&#160;<span style="color: blue">&#160;&#160;&#160; &lt;/</span><span style="color: #a31515">authorization</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 6</span>&#160;<span style="color: blue">&#160; &lt;/</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;</span> </p>
<p style="margin: 0px"><span style="color: #2b91af">&#160;&#160;&#160; 7</span>&#160;<span style="color: blue">&lt;/</span><span style="color: #a31515">location</span><span style="color: blue">&gt;</span> </p>
</p></div>
<p>I have not updated the zip file with these web.config settings; let me know if anyone would prefer that I add it. I hope this helps some of you! </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2007/12/10/aspnet-mvc-membership-basics/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>CssHandler: CSS + Variables</title>
		<link>http://www.squaredroot.com/2007/11/16/csshandler-first-release/</link>
		<comments>http://www.squaredroot.com/2007/11/16/csshandler-first-release/#comments</comments>
		<pubDate>Fri, 16 Nov 2007 16:54:00 +0000</pubDate>
		<dc:creator>Troy Goode</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[CodePlex]]></category>
		<category><![CDATA[CssHandler]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">/post/2007/11/16/CssHandler-First-Release.aspx</guid>
		<description><![CDATA[It&#8217;s been more than three and a half years since Rory Blyth said &#8220;screw standards — let&#8217;s add variable support to CSS right this minute.&#8221; In retrospect, adding variables to CSS seems obvious; everyone is asking about it. There have even been one or two other .Net solutions developed, though Rory&#8217;s solution has remained my [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been more than three and a half years since <a href="http://www.neopoleon.com">Rory Blyth</a> said &#8220;<a href="http://www.neopoleon.com/home/blogs/neo/archive/2004/03/06/8705.aspx">screw standards — let&#8217;s add variable support to CSS right this minute</a>.&#8221; In retrospect, adding variables to CSS seems obvious; <a href="http://www.google.com/search?q=css+variables">everyone is asking about it</a>. There have even been <a href="http://www.codeproject.com/useritems/CSSVariables.asp">one</a> or <a href="http://aspnetresources.com/articles/variables_in_css.aspx">two</a> other .Net solutions developed, though Rory&#8217;s solution has remained my favorite. With CSS2 barely working and <a href="http://www.w3.org/Style/CSS/current-work">CSS3 not addressing the issue</a>, those of us who are tired of repeating ourselves throughout our CSS files have no choice but to take matters into our own hands.</p>
<p>With that in mind I set out to update Rory&#8217;s code. Not that there was anything wrong with it in the first place, of course (this is where I try to tactfully avoid being drawn as a jerkasaurus in one of Rory&#8217;s comics), but Rory did whip the code up for a <a href="http://www.padnug.org/">PADNUG</a> meeting and that <em>was</em> about 3.5 million years ago (give or take many orders of magnitude). It was time to bring the CssHandler into 2007! Conveniently right before 2008.</p>
<p>Lo and behold, someone else had beat me to it. <a href="http://codingpatterns.blogspot.com/">Gabe Moothart</a> had already <a href="http://www.codeplex.com/CssHandler/">uploaded the CssHandler to CodePlex</a>, and even improved upon it. While Rory&#8217;s code originally only allowed variable declarations &amp; references and stripped comments, Gabe&#8217;s version also resolved application-relative paths (e.g.: &#8220;~/blah/blah.gif&#8221;) into browser friendly paths. I had further goals in mind though, and Gabe was kind enough to add me onto the project.</p>
<p>With my updates complete, I am now proud to present&#8230;</p>
<h2>CssHandler 1.0</h2>
<p><em>Features</em>:</p>
<ul>
<li>Define variables for later reference.</li>
<li>Resolve application relative paths.</li>
<li>Only link to one CSS file from your HTML page. Let the CssHandler combine additional CSS files at runtime to limit HTTP connections and share variable definitions across files.</li>
<li>All comments are stripped before render.</li>
<li>Most white-space is stripped before render.</li>
<li>HttpHandler can be mapped to *.css or can be referenced as CssHandler.axd and passed a CSS file in the query string.</li>
</ul>
<p><em>Bugs fixed</em>:</p>
<ul>
<li>The @define{&#8230;} block is no longer sent down to the client.</li>
<li>Similarly named variables no longer present a problem.</li>
</ul>
<p><em>Example</em>:</p>
<p>The HTML references &#8220;styles.css&#8221;, which looks like:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/CssHandlerCSSVariablesLove_A91A/CssHandler_stylecss_2.jpg"><img style="border-width: 0px" src="/image.axd?picture=WindowsLiveWriter/CssHandlerCSSVariablesLove_A91A/CssHandler_stylecss_thumb.jpg" border="0" alt="CssHandler_stylecss" width="458" height="332" /></a></p>
<p>As seen above, &#8220;styles.css&#8221; references &#8220;styles2.css&#8221; via the @import statement, which looks like:</p>
<p><a href="/image.axd?picture=WindowsLiveWriter/CssHandlerCSSVariablesLove_A91A/CssHandler_style2css_2.jpg"><img style="border-width: 0px" src="/image.axd?picture=WindowsLiveWriter/CssHandlerCSSVariablesLove_A91A/CssHandler_style2css_thumb.jpg" border="0" alt="CssHandler_style2css" width="459" height="55" /></a></p>
<p>The CssHandler then:</p>
<ol>
<li>Intercepts the browser&#8217;s request for &#8220;styles.css&#8221;.</li>
<li>Resolves the two URLs that are using application relative paths.</li>
<li>Replaces the @import directive with the text from &#8220;styles2.css&#8221;.</li>
<li>Strips all comments from the CSS.</li>
<li>Replaces all referenced variables with their defined values.</li>
<li>Compresses most of the CSS&#8217;s white-space.</li>
<li>Renders the following to the browser:</li>
</ol>
<p><a href="/image.axd?picture=WindowsLiveWriter/CssHandlerCSSVariablesLove_A91A/CssHandler_rendered_2.jpg"><img style="border-width: 0px" src="/image.axd?picture=WindowsLiveWriter/CssHandlerCSSVariablesLove_A91A/CssHandler_rendered_thumb.jpg" border="0" alt="CssHandler_rendered" width="461" height="40" /></a></p>
<p>I hope you find it as useful as I have. Many thanks to Rory Blyth and Gabe Moothart. Hopefully CSS4 will add variables and we&#8217;ll never have to use this again!</p>
<p><a href="http://www.codeplex.com/CssHandler/">Visit the project&#8217;s CodePlex site to download</a>.</p>
<p><strong>Update (Dec. 2, 2007):</strong> Rory has posted and <a href="http://www.neopoleon.com/home/blogs/neo/archive/2007/11/23/28201.aspx">given his blessing</a>, so to speak. Thanks Rory! </p>
<div style="text-align: center;"><a href="http://www.dotnetkicks.com/kick/?url=http://www.squaredroot.com/2007/11/16/csshandler-first-release/" style="border:0; position: relative; top: -2px;"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.squaredroot.com/2007/11/16/csshandler-first-release/" style="border:0;" alt="Kick It on DotNetKicks.com" /></a><a href="http://dotnetshoutout.com/Submit?url=http://www.squaredroot.com/2007/11/16/csshandler-first-release/" style="border: 0;"><img src="http://dotnetshoutout.com/image.axd?url=http://www.squaredroot.com/2007/11/16/csshandler-first-release/" style="border:0px" alt="Shout It on DotNetShoutOuts.com" /></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.squaredroot.com/2007/11/16/csshandler-first-release/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
