<?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>PeterKellner.net &#187; MSDN Articles</title>
	<atom:link href="http://peterkellner.net/category/msdn-articles/feed/" rel="self" type="application/rss+xml" />
	<link>http://peterkellner.net</link>
	<description>Microsoft Focused, JavaScript,HTML5 (ExtJS, SenchaTouch &#38; Windows 8 Metro)</description>
	<lastBuildDate>Fri, 11 May 2012 16:43:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Third Article Published on MSDN! ASP.NET 2.0, Membership Meets Atlas</title>
		<link>http://peterkellner.net/2006/08/02/third-article-published-on-msdn-aspnet-20-membership-meets-atlas/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=third-article-published-on-msdn-aspnet-20-membership-meets-atlas</link>
		<comments>http://peterkellner.net/2006/08/02/third-article-published-on-msdn-aspnet-20-membership-meets-atlas/#comments</comments>
		<pubDate>Wed, 02 Aug 2006 22:30:55 +0000</pubDate>
		<dc:creator>Peter Kellner</dc:creator>
				<category><![CDATA[ASP.NET 2.0]]></category>
		<category><![CDATA[Atlas/AJAX]]></category>
		<category><![CDATA[Membership]]></category>
		<category><![CDATA[MSDN Articles]]></category>
		<category><![CDATA[ObjectDataSource]]></category>

		<guid isPermaLink="false">http://peterkellner.net/?p=41</guid>
		<description><![CDATA[Microsoft published my third article in a series on how to use Membership in ASP.NET 2.0 with an ObjectDataSource.  That is, extending Membership into three tiers.  This article takes what was developed in article two and adds Atlas extensions to make it work even better.  The Article on MSDN uses the March CTP (Community Technology Preview).  There is an update on my blog as well as a download to make it work correctly with the June CTP.]]></description>
			<content:encoded><![CDATA[<p>Microsoft just published my third article. This one is titled: &quot;Member/Role Management with IIS, Part 3: AJAX Enhancements with Microsoft’s Atlas&quot;.</p>
<p>You can find it on <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/membershipeditoratlas.asp">MSDN here</a>, or on <a href="http://peterkellner.net/?p=1">my blog here</a>.</p>
<p>Here is the introduction.</p>
<h2>Introduction</h2>
<p>This article extends one of the web pages developed in Part II of this series using Microsoft’s implementation of AJAX called Atlas. It utilized two techniques for reducing web server traffic to the browser to enhance the users web experience. The first technique uses the UpdatePanel tags to limit the refreshed area of the web page to limited areas and the second has to do with implementing some javascript using Atlas techniques so that the web page is updated on every key stroke in a textbox. A user list is displayed based on what is actively typed into this textbox. After reading this article the developer will be able to implement AJAX (Microsoft’s implementation Atlas) in their own application.</p>
]]></content:encoded>
			<wfw:commentRss>http://peterkellner.net/2006/08/02/third-article-published-on-msdn-aspnet-20-membership-meets-atlas/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Adding Personalization via Profiles to the ObjectDataSource in ASP.NET 2.0</title>
		<link>http://peterkellner.net/2006/03/13/adding-personalization-via-profiles-to-the-objectdatasource-in-aspnet-20/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=adding-personalization-via-profiles-to-the-objectdatasource-in-aspnet-20</link>
		<comments>http://peterkellner.net/2006/03/13/adding-personalization-via-profiles-to-the-objectdatasource-in-aspnet-20/#comments</comments>
		<pubDate>Tue, 14 Mar 2006 00:33:03 +0000</pubDate>
		<dc:creator>Peter Kellner</dc:creator>
				<category><![CDATA[.Net 2.0]]></category>
		<category><![CDATA[ASP.NET 2.0]]></category>
		<category><![CDATA[Membership]]></category>
		<category><![CDATA[MSDN Articles]]></category>
		<category><![CDATA[ObjectDataSource]]></category>

		<guid isPermaLink="false">http://peterkellner.net/?p=29</guid>
		<description><![CDATA[<p>This article explains the mechanics involved in extending the ObjectDataSource (developed in the previous article in this <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp">MSDN Membership Security Series</a>) to handle personalization information using the ASP.NET 2.0 custom provider facility. Then, it goes on to explains some fancy tricks you can do with this ObjectDataSource to make accessing membership even easier. Finally it presents a <a href="http://painfreeods.peterkellner.net/Default.aspx">free tool available on the web</a> that lets you cut and paste part of your web.config file into a web page and out comes a ready-to-compile C-Sharp ObjectDataSource.</p>]]></description>
			<content:encoded><![CDATA[<p>Also published on Microsoft’s MSDN Network at <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/membershipeditorwithprofile.asp">Microsoft ASP.NET 2.0 Member/Role Management with IIS, Part 4: Adding Personalization with Profiles to the ObjectDataSource</a></p>
<p>Applies to:</p>
<ul>
<li>Microsoft ASP.NET 2.0 </li>
<li>Microsoft Visual Studio 2005 </li>
<li>Microsoft Internet Information Services </li>
</ul>
<p><a href="http://livedemos.peterkellner.net/AJAXDemo/DefaultWithProfile.aspx"></a></p>
<p> <span id="more-20"></span>
<p><a href="http://livedemos.peterkellner.net/AJAXDemo/DefaultWithProfile.aspx">Run Live Demonstration Of Personalization in Membership Technology</a></p>
<p><a href="http://painfreeods.peterkellner.net/">Go to the Web Site to Create Your Own ObjectDataSource From Your Own Web.Config</a></p>
<p><a href="http://download.microsoft.com/download/3/6/5/36559e56-c23f-47cc-9442-a160b3f1b99c/MembershipEditorWithProfile.msi">Click Here for Source Code Associated With This Article</a></p>
<p><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp">Microsoft ASP.NET 2.0 Member/Role Management with IIS, Part 2: Implementation</a><span></span> </p>
<hr  ="&lt;hr" />
<h4>Contents</h4>
<p> <a href="#Introduction">Introduction</a>   <br /><a href="#Background">Background</a>   <br /><a href="#Why">Why Do We Need This?</a>   <br /><a href="#Adding">Adding Profile Information to the ObjectDataSource</a>   <br /><a href="#Using">Using the Profile Generating Website</a>   <br /><a href="#Build">Build A Simple Web Page</a>   <br /><a href="#Conclusions">Conclusions</a>   <br /> <br />
<h2 id="Introduction">Introduction</h2>
<p>This article extends one of the web pages developed in <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp">Part II of this series</a> using Microsoft&#8217;s Profile feature. In Part II, the Membership API was encapsulated in an ObjectDataSource. This allowed the developer to have a drop in web page for the web site administrator to use in an web site project for editing membership. This tools allowed for similar capability to the the web site manager tool included in Visual Studio 2005 (VS2005). It is necessary because using that web configuration tool included with VS2005 is problematic and should not be used in a production web site.</p>
<p>This article explains how the encapsulation of Membership can be extended to include Profile (personalization) information for users. The designers of Membership included a very basic set of attributes to associate with Members (logged in users). The Profile API provided by Microsoft allows for additional information to be attached to each member. Typically, this information would include things like: first name, last name, home address, favorite color schemes or anything else the developer may want to associate with a logged in member. By personalizing the site to the member logged in, it likely increases the chance the user will return and be more comfortable while visiting.</p>
<h2>Background</h2>
<p>ASP.NET has done an outstanding job of making the profile information associated with a logged in user very easy to access programmatically. They have done this by using their Provider technology to create a typed class that the developer can access with intellisense property values. What does this mean? This means that the profile information is declaratively defined as XML in the web.config file. The example below shows the lines that have been added to the &lt;system.web&gt; section of the web.config.</p>
<p> 
<pre class="csharpcode"> <span class="kwrd">&lt;</span><span class="html">system</span> .<span class="attr">web</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">profile</span> <span class="attr">defaultProvider</span><span class="kwrd">=&quot;SqlProfileProvider&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">providers</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">remove</span> <span class="attr">name</span><span class="kwrd">=&quot;AspNetSqlProfileProvider&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;SqlProfileProvider&quot;</span>
       <span class="attr">type</span><span class="kwrd">=&quot;System.Web.Profile.SqlProfileProvider&quot;</span>
       <span class="attr">connectionStringName</span><span class="kwrd">=&quot;LocalSqlServer&quot;</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">providers</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">properties</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;FirstName&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;LastName&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;AdvancedMode&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;bool&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">group</span> <span class="attr">name</span><span class="kwrd">=&quot;Address&quot;</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;Street&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span><span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;City&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span><span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;State&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span><span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;Zip&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;/</span><span class="html">group</span><span class="kwrd">&gt;</span>    <span class="kwrd">&lt;/</span><span class="html">properties</span><span class="kwrd">&gt;</span>  <span class="kwrd">&lt;/</span><span class="html">profile</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">system</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>These new properties defined by Microsoft can be accessed in C# at run time very simply. Below are a few lines of code showing how this can be done in a typical codebehind page. These lines of code are taken from the button update event on the page UpdateProfileSimple.aspx included in the download associated with this article.</p>
<p></p>
<pre class="csharpcode"> <span class="kwrd">protected</span> <span class="kwrd">void</span> ButtonUpdate_Click(<span class="kwrd">object</span> sender,
    EventArgs e)
{
  Profile.FirstName = TextBoxFirstName.Text;
  Profile.LastName = TextBoxLastName.Text;
  Profile.Save();
}</pre>
<p></p>
<p>Profile is available everywhere because it is a static class generated from the Web.Config section shown above. Because it is an actual class, the properties FirstName and LastName are available from VS2005&#8242;s intellisense and are type safe. No incorrectly typing them and getting syntax errors.</p>
<p>In the simple example below (UpdateProfileSimple.aspx), it is necessary to first pre load the textboxes when the user logs in. This can be done in the pageload event as follows.</p>
<p></p>
<pre class="csharpcode"> <span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)
{
  <span class="rem">// Only allow for profile update when a user is logged in</span>
  MembershipUser mu = Membership.GetUser();
  <span class="kwrd">if</span> (mu == <span class="kwrd">null</span>)
  {
    ButtonUpdate.Enabled = <span class="kwrd">false</span>;
  }
  <span class="kwrd">else</span>
  {
    <span class="kwrd">if</span> (!IsPostBack)
    {
      TextBoxFirstName.Text = Profile.FirstName;
      TextBoxLastName.Text = Profile.LastName;
    }
  }
}</pre>
<p></p>
<p>There are a couple things to notice in the above page_load event. First, if no user is logged in, the update button is disabled. This is because it would be meaningless to press the update button if there was no current user to update. It is important to mention that this article does not address dealing with anonymous users. That is a whole different topic. Very interesting, but beyond the scope of this article. Also notice that the first and last names are only loaded when the page is not a postback. That means that only the first time this page is loaded will the data will be loaded from the Profile datastore. After the first time, the data is stored in the page&#8217;s viewstate and no longer will have to be retrieved from the static Profile class. This is important to note because each time a profile property is accessed, a round trip to the membership database occurs. This is the reason using the Profile classes are often referred to as chatty with the database. Something to think about, and keep in mind when designing your application.</p>
<p>There are several good articles that go into more detail on using the profile provider. <a href="http://weblogs.asp.net/scottgu/archive/2005/10/18/427754.aspx">Scott Gu posts in his blog</a> an excellent how to guide that steps you through creating basic Membership in a web application including customized Profile information. A good one in MSDN is <a href="http://msdn.net/msdnmag/issues/05/10/CuttingEdge/">Personalization and User Profiles in ASP.NET 2.0 by Dino Esposito</a>. Another one of my favorites is <a href="http://www.odetocode.com/Articles/440.aspx">Profiles in ASP.NET 2.0 by Scott Allen</a>.</p>
<h2 id="#Why">Why Do We Need This? </h2>
<p>The questions comes up, why do we need an ObjectDataSource that encapsulates our Profile information? The answer is this. Even though ASP.NET does a wonderful job of giving us programmatic access to the Profile class it does not gives a simple way to view or update this data by binding it directly to any controls like gridview or detailsview. Joshua Flanagan wrote a very nice tool called <a href="http://peterkellner.net/download-manager/">ProfileView</a> that you can see on his blog. Basically, he wrote an ASP.NET 2.0 server control that enables users to view and/or edit the Profile data. It does this using reflection at runtime to figure out what the profile information is, then it shows it.</p>
<p>The ObjectDataSource allows you at design time to make the presentation layer look exactly as you like. It also allows for viewing multiple members profiles at the same time. Take a look at the screen shot below to see what a gridview looks like using on ObjectDataSource generated using this technology. Also, you can <a href="http://livedemos.peterkellner.net/AJAXDemo/DefaultWithProfile.aspx">play with it live right here</a>.</p>
<table border="0" cellpadding="10" width="200">
<tbody>
<tr>
<td><a href="http://peterkellner.net/images/MembershipProvider/membership.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/membership_t.jpg" width="341" height="388" /></a></td>
<td><img src="/images/MembershipProvider/membership_namesonly.jpg" /></td>
</tr>
</tbody>
</table>
<p>At first glance, this is identical the screen developed in<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp"> Part 2 of this series</a>. If you look closer however (or at the picture to the right of the first one), you&#8217;ll notice that there are two new columns. First Name and Last Name. Both of these columns have data retrieved from the Membership Profile data provider we have been discussing. In the next section the details of what changes to the ObjectDataSource in the previous article have been made to allow this to happen. Something very important to note however, is that since the ObjectDataSource is basically a static class, the profile information in that ObjectDataSource will not automatically change when the web.config is changed (unlike <a href="http://flimflan.com/blog/ProfileView.aspx">Joshua Flanagan&#8217;s solution</a> which will change).</p>
<h2 id="Adding">Adding Profile Information to the ObjectDataSource</h2>
<p>As was mentioned earlier, the ObjectDataSource developed here is 100% based on the one developed in <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp">Part II of this MSDN series, Implementation</a>. The discussion here assumes all the previous code is understood and only explains the additions to support the Profile feature. All the code described here is what gets generated by the <a href="http://painfreeods.peterkellner.net/">ObjectDataSource generator on Peter Kellner&#8217;s Blog</a> (this tool is discussed in greater detail in the next major section of this article). In this section we go through the details of what gets added. In the next section it is shown how the steps to generating the source described here from an existing web.config file.</p>
<h3>Changing Class Names </h3>
<p>Since it&#8217;s possible the ObjectDataSource geneated here may be used in the same project as the one provided with Part 2 of this series, all the public names have been changed to avoid naming conflicts. For example, the class name MembershipUserODS has been renamed to MembershipUserAndProfileODS. The RoleData class has been renamed RoleDataForMP and the MemberhipUserWrapper class has been renamed MembershipUserWrapperForMP (MP standing for MembershipProfile).</p>
<h3>The Insert Method</h3>
<p>The method signature of Insert now contains all the names of the Profile properties. In addition to Membership.CreateUser being called, the Profile properties must be saves also with the Profile.Save() method. Below is the complete Insert method for an example set of profile properties (profile properties are stored in the web.config file and will likely be different for each asp.net web application).</p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Insert, <span class="kwrd">true</span>)]
<span class="kwrd">public</span> <span class="kwrd">void</span> Insert(<span class="kwrd">string</span> userName, <span class="kwrd">bool</span> isApproved,
    <span class="kwrd">string</span> comment, DateTime lastLockoutDate,
    DateTime creationDate,<span class="kwrd">string</span> email,
    DateTime lastActivityDate, <span class="kwrd">string</span> providerName,
    <span class="kwrd">bool</span> isLockedOut,DateTime lastLoginDate,
    <span class="kwrd">bool</span> isOnline, <span class="kwrd">string</span> passwordQuestion,
    DateTime lastPasswordChangedDate, <span class="kwrd">string</span> password,
    <span class="kwrd">string</span> passwordAnswer, <span class="kwrd">string</span> firstName,
    <span class="kwrd">string</span> lastName, <span class="kwrd">bool</span> advancedMode,
    <span class="kwrd">string</span> address_Street, <span class="kwrd">string</span> address_City,
    <span class="kwrd">string</span> address_State, <span class="kwrd">string</span> address_Zip
    )
{

    MembershipCreateStatus status;
    Membership.CreateUser(userName, password, email,
        passwordQuestion, passwordAnswer,
        isApproved, <span class="kwrd">out</span> status);

    <span class="kwrd">if</span> (status != MembershipCreateStatus.Success)
    {
     <span class="kwrd">throw</span> <span class="kwrd">new</span> ApplicationException(status.ToString());
    }

    MembershipUser mu = Membership.GetUser(userName);
    mu.Comment = comment;
    Membership.UpdateUser(mu);
    ProfileCommon pc =
     (ProfileCommon)ProfileBase.Create
        (mu.UserName, <span class="kwrd">true</span>);
    pc.FirstName = firstName;
    pc.LastName = lastName;
    pc.AdvancedMode = advancedMode;
    pc.Address.Street = address_Street;
    pc.Address.City = address_City;
    pc.Address.State = address_State;
    pc.Address.Zip = address_Zip;
    pc.Save();
}</pre>
<p></p>
<p>Something also to take note of is the the variable names are constructed with an underscore because variable names with periods would not work. Notice in particular the properties that are nested such as address_state. This refers to the Profile property pc.Address.State.</p>
<h3>The Delete Method</h3>
<p>The delete method has no changes. This is because the membership class takes care of removing all profile information when Membership.DeleteUser() is invoked.</p>
<h3>The Update Method</h3>
<p>The Update method is changed. To the parameter list is added all the parameters representing properties. Then, in the update method itself the profile information is update after the Membership is updated. below is a portion of the code for this using the example properties.</p>
<p></p>
<pre class="csharpcode">ProfileCommon pc = (ProfileCommon)ProfileBase.
      Create(mu.UserName, <span class="kwrd">true</span>);
    pc.FirstName = firstName;
    pc.LastName = lastName;
    pc.AdvancedMode = advancedMode;
    pc.Address.Street = address_Street;
    pc.Address.City = address_City;
    pc.Address.State = address_State;
    pc.Address.Zip = address_Zip;
    pc.Save();</pre>
<p></p>
<h3>The Get (Select) Methods </h3>
<p>Just like in Part 2 of this series, there are several Get Methods provided. No additional get methods are added, however now, because of the addition of the Profile properties, the Get Method&#8217;s return profile properties include Membership Properties as well as Profile properties. This is handled by first retrieving the Membership data with GetUser or GetUsers methods, then adding the additional properties from the profile to the Generic list which will get returned. The critical section of code that does this is next.</p>
<p></p>
<pre class="csharpcode">MembershipUserCollection muc = Membership.GetAllUsers();
<span class="kwrd">foreach</span> (MembershipUser mu <span class="kwrd">in</span> muc)
{
 <span class="kwrd">if</span> ((returnAllApprovedUsers==<span class="kwrd">true</span> &amp;amp;&amp;amp; mu.IsApproved==<span class="kwrd">true</span>) ||
 (returnAllNotApprovedUsers==<span class="kwrd">true</span> &amp;amp;&amp;amp; mu.IsApproved==<span class="kwrd">false</span>))
 {
    MembershipUserWrapperForMP md =
      <span class="kwrd">new</span> MembershipUserWrapperForMP(mu);
    ProfileCommon pc = (ProfileCommon)ProfileBase.Create
      (mu.UserName, <span class="kwrd">true</span>);
    md.FirstName = pc.FirstName;
    md.LastName = pc.LastName;
    md.AdvancedMode = pc.AdvancedMode;
    md.Address_Street = pc.Address.Street;
    md.Address_City = pc.Address.City;
    md.Address_State = pc.Address.State;
    md.Address_Zip = pc.Address.Zip;
    memberList.Add(md);
 }
}</pre>
<p></p>
<h3>Sorting Support </h3>
<p>Sorting the ObjectDataSource&#8217;s columns is also supported. Just as in Membership Part 2, this is supported using anonymous delegates. Basically, a comparater method is created with an anonymous delegate that takes two parameters. The left and right hand side of a sort operation. Then, using this comparater, the generic List is sorted before being returned to the caller. This very clever construct was inspired by <a href="http://blogs.tedneward.com">Ted Neward </a>at a Code Camp in Portland.</p>
<p>Just like the MembershipUser properties, Profile properties are handled the same way so that those values can be sorted in a GridView by clicking on the column headers. Below is the creation of one comparater method.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">switch</span> (sortDataBase)
{
  <span class="kwrd">case</span> &amp;quot;FirstName&amp;quot;:
    comparison = <span class="kwrd">new</span>
      Comparison&lt;membershipuserwrapperformp&gt;(
       <span class="kwrd">delegate</span>(MembershipUserWrapperForMP lhs,
            MembershipUserWrapperForMP rhs)
       {
           <span class="kwrd">return</span> lhs.FirstName.CompareTo(
              rhs.FirstName);
       }
     );
    <span class="kwrd">break</span>;&lt;/membershipuserwrapperformp&gt;</pre>
<p></p>
<h3>The Class associated with the Generic List </h3>
<p>The final piece of code that has to be extended is the Class that is returned from the Get methods. That is the generic list which is declared as follows.</p>
<p></p>
<pre class="csharpcode"> <span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)
{
  <span class="rem">// Only allow for profile update when a user is logged in</span>
  MembershipUser mu = Membership.GetUser();
  <span class="kwrd">if</span> (mu == <span class="kwrd">null</span>)
  {
    ButtonUpdate.Enabled = <span class="kwrd">false</span>;
  }
  <span class="kwrd">else</span>
  {
    <span class="kwrd">if</span> (!IsPostBack)
    {
      TextBoxFirstName.Text = Profile.FirstName;
      TextBoxLastName.Text = Profile.LastName;
    }
  }
}</pre>
<p></p>
<h3>One Final Trick on Using the ObjectDataSource </h3>
<p>ObjectDataSource&#8217;s are great for using with databound ASP.NET&#8217;s controls such as GridView and DetailsView. They are wired such that the get methods, update, delete and insert line up perfectly with what those controls are looking for. However, the ODS&#8217;s can be used directly without having a presentation style control associated with them. For example, the Insert method associated with adding a new member in the included code from the asp.net page MembershipWithProfile.aspx uses the ObjectDataSource to insert even though it is not bound to any control on the page. The data it is entering is coming from TextBox&#8217;s in a table. Below is the Insert code used. Notice how straight forward it is to use compared do creating an inserter and doing all the ADO without this class.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> ButtonNewUser_Click(<span class="kwrd">object</span> sender, EventArgs e)
{

    MembershipUtilities.MembershipUserAndProfileODS
      membershipUserAndProfileODS =
        <span class="kwrd">new</span> MembershipUserAndProfileODS();

    membershipUserAndProfileODS.Insert(
        TextBoxUserName.Text,
        CheckboxApproval.Checked,
        <span class="kwrd">string</span>.Empty,
        DateTime.Now,
        DateTime.Now,
        TextBoxEmail.Text,
        DateTime.Now,
        <span class="kwrd">string</span>.Empty,
        <span class="kwrd">false</span>,
        DateTime.Now,
        <span class="kwrd">false</span>,
        TextBoxPasswordQuestion.Text,
        DateTime.Now,
        TextBoxPassword.Text,
        TextBoxPasswordAnswer.Text,
        TextBoxFirstName.Text,
        TextBoxLastName.Text,
        <span class="kwrd">false</span>,
        <span class="kwrd">string</span>.Empty,
        <span class="kwrd">string</span>.Empty,
        <span class="kwrd">string</span>.Empty,
        <span class="kwrd">string</span>.Empty);

    GridViewMemberUser.DataBind();
    TextBoxUserName.Text = <span class="kwrd">string</span>.Empty;
    TextBoxFirstName.Text = <span class="kwrd">string</span>.Empty;
    TextBoxLastName.Text = <span class="kwrd">string</span>.Empty;
    TextBoxPassword.Text = <span class="kwrd">string</span>.Empty;
    TextBoxEmail.Text = <span class="kwrd">string</span>.Empty;
    TextBoxPasswordAnswer.Text = <span class="kwrd">string</span>.Empty;
    TextBoxPasswordQuestion.Text = <span class="kwrd">string</span>.Empty;
    CheckboxApproval.Checked = <span class="kwrd">false</span>;
}</pre>
<p></p>
<p>Because this is an actual class with properties, using the ObjectDataSource class is type safe. For example, in the code below, the user may want to count how many zipcodes in the membership database that begin with 9. Here is the code to do it. Notice how Address_Zip is used in a type safe way.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">void</span> ButtonZipCount_Click
    (<span class="kwrd">object</span> sender, EventArgs e)
{
    MembershipUtilities.MembershipUserAndProfileODS
        membershipUserAndProfileODS =
        <span class="kwrd">new</span> MembershipUserAndProfileODS();

    List&lt;membershipuserwrapperformp&gt; li =
        membershipUserAndProfileODS.GetMembers
        (<span class="kwrd">string</span>.Empty);

    <span class="kwrd">int</span> count = 0;
    <span class="kwrd">foreach</span> (MembershipUserWrapperForMP mu <span class="kwrd">in</span> li)
    {
        <span class="kwrd">if</span> (mu.Address_Zip.StartsWith(&amp;quot;9&amp;quot;))
        {
            count++;
        }
    }
}&lt;/membershipuserwrapperformp&gt;</pre>
<p></p>
<h2 id="Using">Using the Profile Generating Website </h2>
<p>All the changes listed in the previous section could be done by hand, however this would be very tedious. To make this process much easier, a code generator has been developed which takes as input the applications web.config file&#8217;s &lt;System.Web&gt; section. The idea is to cut this out of the web.config file and paste it into the web page which will generate the code for you. Below is a screen show of what the web page looks like. When you get to this page, you must first click on the button in the right column labeled &quot;Click Here to Begin&quot;.</p>
<p>Here is the URL: <a href="http://painfreeods.peterkellner.net/">http://painfreeods.peterkellner.net/</a></p>
<p>&#160;<a href="http://peterkellner.net/images/MembershipProvider/ProfileGenPage.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/ProfileGenPage_t.jpg" /></a></p>
<p>The XML which is pasted into the multi line orange textbox is as follows (you should paste your own in here).</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">system</span>  .<span class="attr">web</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">profile</span> <span class="attr">defaultprovider</span><span class="kwrd">=&quot;SqlProfileProvider&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">providers</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">remove</span> <span class="attr">name</span><span class="kwrd">=&quot;AspNetSqlProfileProvider&quot;</span> <span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;SqlProfileProvider&quot;</span> <span class="attr">connectionstringname</span><span class="kwrd">=&quot;LocalSqlServer&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;System.Web.Profile.SqlProfileProvider&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">providers</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">properties</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;FirstName&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span> <span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;LastName&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span> <span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;AdvancedMode&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;bool&quot;</span> <span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">group</span> <span class="attr">name</span><span class="kwrd">=&quot;Address&quot;</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;Street&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;City&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;State&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;Zip&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;string&quot;</span> <span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;/</span><span class="html">group</span><span class="kwrd">&gt;</span>    <span class="kwrd">&lt;/</span><span class="html">properties</span><span class="kwrd">&gt;</span>  <span class="kwrd">&lt;/</span><span class="html">profile</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">system</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>Now, if the &quot;Show Generated C#&quot; button is pressed, the complete ObjectDataSource will be created. This code can then be cut and pasted into the App_Code directory of the web project. Here is what the screen looks like.</p>
<p><a href="http://peterkellner.net/images/MembershipProvider/ProfileGenSrc.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/ProfileGenSrc_t.jpg" /></a></p>
<p>There are some limitations to this code generation technology. First is that there can only be one level of nesting. That is, there can be no groups of groups. Just one level of grouping is allowed as is shown here. It is OK to have multiple groups, just not nested. Another limitation is the type associated with the name must be a C# type. That is, string, bool,DateTime,etc. The final limitation (known about) is that it can not handle Array or Collection type properties. All properties must be single valued.</p>
<p>At this point, error checking is minimal so if the limitations are exceeded, something will likely come out but it may not be what was desired.</p>
<h2 id="Build">Build A Simple Web Page</h2>
<p>Now that the C# class has been generated, the next steps are very straight forward. For those who have not built a GridView based on an ObjectDataSource, here is a pictorial step by step of the 9 things needed to do to have a very simple gridview control in under 5 minutes.</p>
<table border="0" cellpadding="2" width="694">
<caption>Building a Web Page From Scratch<br />
    <br /></caption>
<tbody>
<tr>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step1.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step1_t.jpg" width="250" height="186" /></a></p>
<p>1. Add a New Web Page to the Project</p>
</td>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step2.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step2_t.jpg" width="250" height="179" /></a></p>
<p>2. Choose Web Page and Name it</p>
</td>
</tr>
<tr>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step3.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step3_t.jpg" width="250" height="206" /></a></p>
<p>3. Add a GridView and an ObjectDataSource. Associate them</p>
</td>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step4.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step4_t.jpg" /></a></p>
<p>4. Configure the ObjectDataSource by Assigning the Class</p>
</td>
</tr>
<tr>
<td>
<p>&#160;</p>
<p><a href="http://peterkellner.net/images/MembershipProvider/step5.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step5_t.jpg" width="250" height="174" /></a></p>
<p>5. Choose the Get Method (Use Default)</p>
</td>
<td>
<p>&#160;</p>
<p><a href="http://peterkellner.net/images/MembershipProvider/step6.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step6_t.jpg" width="250" height="174" /></a></p>
<p>6. Choose the Update Method (Use Default)</p>
</td>
</tr>
<tr>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step7.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step7_t.jpg" width="250" height="174" /></a></p>
<p>7. Choose the Insert Method (Choose Default)</p>
</td>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step8.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step8_t.jpg" width="250" height="174" /></a></p>
<p>8. Choose the Delete Method (Choose Default)</p>
</td>
</tr>
<tr>
<td>
<p><a href="http://peterkellner.net/images/MembershipProvider/step9.jpg"><img border="0" src="http://peterkellner.net/images/MembershipProvider/step9_t.jpg" width="250" height="154" /></a></p>
<p>9. Run it! (OK, had to enable edit and delete on Gridview. No more boxes left)</p>
</td>
<td>&#160;</td>
</tr>
</tbody>
</table>
<p>The code in the associated source to this article has a web apge ( MembershipWithProfile.aspx) which is very similar to what is done here.</p>
<h2 id="Conclusions">Conclusions</h2>
<p>Profiles are a very powerful way to store information about Membership. It&#8217;s powerful in that with very little coding, lots of additional information about logged in users is available. With this tool, there is now a better way to organize this information and maintain it. Briefly mentioned earlier were the performance implications of using Profile information. It is important to understand what his happening under the covers when this technology is used. As long there is an understanding of what is happening and it is acceptable in the web application being developed, this is a wonderful technology.</p>
<p>Finally, as a plug to the technology that was used in this free ObjectDataSource creator, the Pain Free ObjectDataSource Creator, available through subscription on this blog, lets the developer generate very flexible ObjectDataSource&#8217;s to access database information in SqlServer, MySql and Oracle. Unlike the Profile ODS generator in this article, the ODS generator for databases gives you a large amount of flexibility. An infinite number of getter methods, updaters and inserters can be defined. It works with views, and also stored procedures. Any questions on the Pain Free ODS Generator, <a href="http://peterkellner.net/contact/">click here</a>.</p>
<p>Thanks for reading, and best of luck with your coding projects.</p>
]]></content:encoded>
			<wfw:commentRss>http://peterkellner.net/2006/03/13/adding-personalization-via-profiles-to-the-objectdatasource-in-aspnet-20/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>AJAX Meets ASP.NET 2.0 Membership Management For IIS</title>
		<link>http://peterkellner.net/2006/03/02/ajaxmeetsaspnet20/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ajaxmeetsaspnet20</link>
		<comments>http://peterkellner.net/2006/03/02/ajaxmeetsaspnet20/#comments</comments>
		<pubDate>Thu, 02 Mar 2006 19:34:44 +0000</pubDate>
		<dc:creator>Peter Kellner</dc:creator>
				<category><![CDATA[.Net 2.0]]></category>
		<category><![CDATA[ASP.NET 2.0]]></category>
		<category><![CDATA[Membership]]></category>
		<category><![CDATA[MSDN Articles]]></category>

		<guid isPermaLink="false">/?p=1</guid>
		<description><![CDATA[This article extends one of the web pages developed in Part II of this series using Microsoft's implementation of AJAX called Atlas.  You can view a live demonstration of the technology developed in this article at the URL  <a href="http://livedemos.peterkellner.net/AJAXDemo">http://livedemos.peterkellner.net/AJAXDemo</a>.]]></description>
			<content:encoded><![CDATA[<table border="0" align="left">
<tbody>
<tr>
<td class="title">
<div align="center">Microsoft ASP.NET 2.0 Member/Role Management with IIS, Part 3: AJAX Enhancements with Microsoft&#8217;s Atlas </div>
</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<table border="0" cellpadding="2" width="200">
<tbody>
<tr>
<td>Peter Kellner</td>
</tr>
<tr>
<td><a href="http://peterkellner.net">http://PeterKellner.net</a></td>
</tr>
<tr>
<td>March 2006</td>
</tr>
</tbody>
</table>
<p>Applies to:</p>
<blockquote><p>Microsoft ASP.NET 2.0</p>
<p>Microsoft Visual Studio 2005</p>
<p>Microsoft Internet Information Services</p>
</blockquote>
<p>&#160;<a class="style2" href="http://livedemos.peterkellner.net/">Run Live Demonstration Of AJAX Technology</a></p>
<p class="style2"><a href="http://peterkellner.net/download-manager/">Click Here for Source Code Associated With This Article</a>&#160; </p>
<hr />
<h4>Contents</h4>
<p>Introduction    <br />What is AJAX and Atlas     <br />Background     <br />The AJAX Enhanced Version     <br />Technologies Used in AJAX Enhanced Version     <br />Steps Involved in Building (or upgrading) to AJAX using Atlas     <br />Using UpdatePanel ASP.NET Tag     <br />What is Really Happening     <br />Enhancing the TextBox for User Search     <br />Conclusions&#160; </p>
<p> <span id="more-19"></span><br />
<h2>Introduction</h2>
<p>This article extends one of the web pages developed in Part II of this series using Microsoft&#8217;s implementation of AJAX called Atlas. It utilized two techniques for reducing web server traffic to the browser to enhance the users web experience. The first technique uses the UpdatePanel tags to limit the refreshed area of the web page to limited areas and the second has to do with implementing some javascript using Atlas techniques so that the web page is updated on every key stroke in a textbox. A user list is displayed based on what is actively typed into this textbox. After reading this article the developer will be able to implement AJAX (Microsoft&#8217;s implementation Atlas) in their own application.</p>
<h2>What is AJAX and Atlas</h2>
<p>AJAX is an acronym for <strong>A</strong>synchronous <strong>J</strong>avaScript <strong>A</strong>nd <strong>X</strong>ML. It is a technique for making interactive web applications more responsive. It does this by exchanging small amounts of information between the web server and the web client, thereby reducing the amount of traffic to the web client and making the application more responsive. Without AJAX, each time a page is refreshed (or a postback in generated) the complete page must be retransmitted to the users web browser. This is somewhat mitigated by the local cache on the web browser, but still overkill since most of the information on a postback to a web page does not change.</p>
<p>Atlas is Microsoft&#8217;s implantation of AJAX. It is designed to make it relatively easy for software engineer, already skilled in ASP.NET 2.0 to take advantage of AJAX. Though Atlas has huge capabilities (which, by the way come with a huge learning curve), it is very easy to implement the basics of AJAX and significantly improve the user experience of a web site designed with ASP.NET 2.0 as well be shown in this article.</p>
<p>&#160;&#160;&#160;&#160;<br />
<h2>Background</h2>
<p>Managing membership and roles for ASP.NET 2.0 using ObjectDataSource technology was developed in a previous article published by this author in MSDN ( <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASP2memroleman.asp</a> ). This article stepped through the inner workings of an ObjectDataSource that allowed for the easy creation of gridviews, dataviews, or any other databound control. It also presented a best practices solution in the form of a ASP.NET 2.0 web page (aspx file). The solution allowed for adding, modifying and deleting members, adding and deleting roles, as well as assigning users to roles. The solution is functionally similar to what comes with Visual Studio 2005 under the menu item &quot;Website / ASP.NET Configuration&quot;. The major benefit is that this solution works 100% with IIS 5.1 and 6.0 and gives the software engineer complete customization control of what is presented to the user. It would normally be set to administrator access only. Below is a screen shot of this application previously developed.</p>
<p><a href="http://livedemos.peterkellner.net/AJAXDemo/DefaultNoAjax.aspx"><img border="1" src="http://peterkellner.net/images/ArticleAJAX/DefaultNoAjax.gif" width="450" height="245" /></a></p>
<p><a href="http://livedemos.peterkellner.net/AJAXDemo/DefaultNoAjax.aspx"></a></p>
<p>This application shown above has no AJAX technology in it. This means that every interaction you have with the web form requires a full page refresh of html from the web server. In this case, a picture is not worth very many words, but a URL will certainly make the point. Go to the URL: <a href="http://livedemos.peterkellner.net/AJAXDemo/Default.aspx">http://livedemos.peterkellner.net/AJAXDemo/Default.aspx</a> and play with the web site. Feel completely free to search on this data, add new users, add roles, assign and unassign roles as you please noticing at the time how the page reacts to changes. In particular, note the Search button on top for finding users. This search is a little different than you would normally expect. Instead of looking for exact matches, it effectively finds usernames that begin with what you have typed in the textbox when you press the search button. In the next section, the AJAX enhanced version, the search button is gone and as the username is typed into the textbox, the list of usernames will be automatically updated. This could have been done here also, however it would have caused a complete refresh of the page on every keystroke. Not only would the performance have been unacceptable, it would also have been unusable with all the flashing while typing. This is why in non-AJAX applications, there is almost always a button to press when data is finished being entered.</p>
<p>While you are running the demonstration program, notice at the top of the page there is a link that takes you to the same application without AJAX. Notice that in this application, there is a button for search. Notice also when you check and uncheck the checkboxes to display Manage Roles or Create New Users, those sections turn on and off with a lot of screen refreshing. Also notice the difference when you edit users and assign or unassign roles. </p>
<h2>The AJAX Enhanced Version</h2>
<p>Without actually running the web application, the only visual change the user can see in the AJAX enhanced version of this application is that there is no search button above the user list. This is because with AJAX, as the user types in the search criteria, the list of users is automatically restricted to the search criteria defined by users that begin with what is typed. Notice in the screen shot below, ch is entered into the username textbox and just the usernames beginning with ch automatically appear. </p>
<p><a href="http://livedemos.peterkellner.net/AJAXDemo/Default.aspx"><img border="1" src="http://peterkellner.net/images/ArticleAJAX/DefaultWithAjax.gif" width="450" height="245" /></a>&#160;</p>
<h2>Technologies Used in AJAX Enhanced Version</h2>
<p>Obviously, Microsoft&#8217;s Atlas is the primary technology used to implement AJAX. Atlas has lots of functionality and capability, however in this article (and the code associated with the AJAX enhanced Membership Editor), there is just a small part of Atlas being used. Actually, there are only two technologies going on. One has to do with the updates on the screen not requiring complete html refreshes between postbacks, and the other has to do with extending the functionality of the TextBox control the user enters the name for search. Because the default TextBox has no event associated with characters changing (it only has an event which generates a postback for TextChanged) the TextBox has to be enhanced to deal with the javascript function OnTextChanged. </p>
<h2>Steps Involved in Building (or upgrading) to AJAX using Atlas</h2>
<p>In order to Atlas enable an application you need to make several changes to your project. I won&#8217;t go through all the details, however, the basics are you need to copy in the Atlas script library, modify your web.config, add the atlas dll to your project and finally, add some initializing tags in your aspx pages. The other way to begin working with Atlas (and is it was done to convert the project associated with this article) is first download the new Atlas template from Microsoft&#8217;s Atlas web site. Then, create a new web project using the newly installed Atlas template. Next, rename the default.aspx file in case you have your own, then copy in all your existing libraries and pages. Finally, add your sections to the Atlas enabled web.config file and make sure everything works as before with no Atlas functionality. The final step is to look at the original default.aspx file and copy the Atlas constructs into the headers of an existing page you want to add AJAX capabilities.</p>
<p>It is recommended not to put Atlas in your master page because there are undoubtedly pages that do not need AJAX capability. It is better to put that capability in only the pages you need to keep things simple.</p>
<h2>Using UpdatePanel ASP.NET Tag</h2>
<p>Below is the actual UpdatePanel asp.net control surrounding the checkboxes that let you turn on and off the Role Management, and the Create of New User section. It&#8217;s the two checkboxes half way down the web screen.</p>
<p> 
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:UpdatePanel</span> <span class="attr">ID</span><span class="kwrd">=&quot;UpdatePanelCheckBoxes&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">contenttemplate</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">table</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">tr</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">td</span> <span class="attr">align</span><span class="kwrd">=&quot;left&quot;</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:CheckBox</span> <span class="attr">ID</span><span class="kwrd">=&quot;CheckBoxManageRoles&quot;</span> <span class="attr">Text</span><span class="kwrd">=&quot;Manage Roles&quot;</span>
          <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span> <span class="attr">AutoPostBack</span><span class="kwrd">=&quot;True&quot;</span> <span class="attr">Checked</span><span class="kwrd">=&quot;True&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">td</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">td</span> <span class="attr">align</span><span class="kwrd">=&quot;right&quot;</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:CheckBox</span> <span class="attr">ID</span><span class="kwrd">=&quot;CheckBoxAddUser&quot;</span> <span class="attr">Text</span><span class="kwrd">=&quot;Create New Users&quot;</span>
         <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span> <span class="attr">AutoPostBack</span><span class="kwrd">=&quot;True&quot;</span> <span class="attr">Checked</span><span class="kwrd">=&quot;True&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">td</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;/</span><span class="html">tr</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">table</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;/</span><span class="html">contenttemplate</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">atlas</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>The UpdatePanel control is the control that will most likely be used the most. By surrounding parts of the web page that will change on the postback, this causes the affect of letting this section update with out actually a screen refresh. Essentially, what Atlas does on a page that is Atlas enabled, is it lets all the normal asp.net page lifecycle events process normally (including the Page_Init method) but instead of redisplaying all the HTML in the Page_Render method, it knows to only update code inside the UpdatePanels defined on the web page. In reality what is happening is Atlas is simulating a postback instead of doing a real one.</p>
<p>Something that must be set also is in the ScriptManager tag, for this to actually work, the EnablePartialRendering must be set to true as shown below. If it is not set, then the page behaves as if the UpdatePanel tags are not there.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:ScriptManager</span> <span class="attr">ID</span><span class="kwrd">=&quot;ScripManager&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span>
   <span class="attr">EnablePartialRendering</span><span class="kwrd">=&quot;true&quot;</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">atlas</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>The final thing to do is to surround all the areas on the aspx page with these UpdatePanel tags. Once this is done, VS2005 does a nice job of showing the UpdatePanel areas. The screen shot below shows the actual screen shot of the page used to manage members. Notice all the UpdatePanel tags displayed above the regions. Clicking on the image will display a large one which is much easier to see the details.</p>
<p><a href="http://peterkellner.net/images/ArticleAJAX/vs2005UpdatePanels.gif"><img border="1" src="http://peterkellner.net/images/ArticleAJAX/vs2005UpdatePanels_small.gif" width="450" height="245" /></a></p>
<p>Trigger tags go hand in hand with the UpdatePanel control. Essentially, you can nest trigger controls in the UpdatePanel control and that will specify when the UpdatePanel will actually be posted back. You can specify triggers in two ways. The first way is on some control event such as the EventName &quot;Click&quot; on the button control. The other way is on some control value changing. with that, you would specify the controlID and the property name. There are no examples of triggers in the article download. The code below is just an example of typical code.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:UpdatePanel</span> <span class="attr">ID</span><span class="kwrd">=&quot;Panel1&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">contenttemplate</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:TextBox</span> <span class="attr">ID</span><span class="kwrd">=&quot;TextBox1&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span><span class="kwrd">&gt;&lt;/</span><span class="html">asp</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:Button</span> <span class="attr">ID</span><span class="kwrd">=&quot;Button1&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span><span class="kwrd">&gt;&lt;/</span><span class="html">asp</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;/</span><span class="html">contenttemplate</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">triggers</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:ControlEventTrigger</span> <span class="attr">ControlID</span><span class="kwrd">=&quot;Button1&quot;</span> <span class="attr">EventName</span><span class="kwrd">=&quot;Click&quot;</span> <span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:ControlValueTrigger</span> <span class="attr">ControlID</span><span class="kwrd">=&quot;TextBox1&quot;</span> <span class="attr">PropertyName</span><span class="kwrd">=&quot;Text&quot;</span>   <span class="kwrd">/&gt;</span>
 <span class="kwrd">&lt;/</span><span class="html">triggers</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">atlas</span><span class="kwrd">&gt;</span></pre>
<p></p>
<h2>What is Really Happening</h2>
<p>To understand what is really happening with these UpdatePanel tags, it is helpful to look at the source generated for the web page. Essentially what is happening is that for every control on your web page that is surrounded by the UpdatePanel tags, javascript is created which forces a postback on every click. For example, just looking at the checkboxAddUser control, the following is what is generated.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">td</span> <span class="attr">align</span><span class="kwrd">=&quot;right&quot;</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">label</span> <span class="attr">for</span><span class="kwrd">=&quot;CheckBoxAddUser&quot;</span><span class="kwrd">&gt;</span>Create New Users<span class="kwrd">&lt;/</span><span class="html">label</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">id</span><span class="kwrd">=&quot;CheckBoxAddUser&quot;</span>
   <span class="attr">type</span><span class="kwrd">=&quot;checkbox&quot;</span> <span class="attr">name</span><span class="kwrd">=&quot;CheckBoxAddUser&quot;</span>
   <span class="attr">checked</span><span class="kwrd">=&quot;checked&quot;</span> <span class="attr">onclick</span>=
   <span class="kwrd">&quot;javascript:setTimeout
   ('__doPostBack(\'CheckBoxAddUser\',\'\')', 0)&quot;</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">td</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>This is in addition to all the javascript references that include lots of other javascripts. The bottom line here is that if you include Atlas in your web pages, the actual payload size delivered to your web page in bytes will be significantly larger on the first download then it would be without Atlas. Subsequent requests are of course much smaller because, depending on how you design your page, only small amounts of data need to be returned on each future postback.</p>
<h2>&#160;</h2>
<h2>Enhancing the TextBox for User Search</h2>
<p>The textbox search functionality is a little more tricky. It involves adding javascript which reacts to keystrokes changes. The reason this is necessary is because there is not event in the TextBox control that responds to keyboard clicks. There is only an event that reacts to text changes which is not good enough for our needs. In this application, I am using javascript from The <a href="http://aspadvice.com/blogs/garbin/archive/2006/02/25/15360.aspx">Atlas Notes Blog</a> by Garbin</p>
<p>The steps necessary to make this work are as follows:</p>
<p>Add the TextChangedBehavior.js to the ScriptLibrary folder</p>
<p>Add just below the &lt;form&gt; tag of your aspx page a line that includes the new javascript</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:ScriptManager</span> <span class="attr">ID</span><span class="kwrd">=&quot;sm&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span>
     <span class="attr">EnablePartialRendering</span><span class="kwrd">=&quot;true&quot;</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">scripts</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">atlas</span> <span class="attr">:ScriptReference</span>
     <span class="attr">Path</span><span class="kwrd">=&quot;ScriptLibrary/TextChangedBehavior.js&quot;</span> <span class="kwrd">/&gt;</span>
 <span class="kwrd">&lt;/</span><span class="html">scripts</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">atlas</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>Add a small javascript code piece to your web page that your TextBox control will reference</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
  <span class="kwrd">function</span> onTextChange() {
    __doPostBack(<span class="str">'GridViewMemberUser'</span>,<span class="str">''</span>) ;
        }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>And, finally add another xml-script to the bottom of your web page that declaratively tells the Atlas processor to add this new javascript capability to the TextBoxSearchUser Control. This essentially maps the onclick event of the TextBoxSearchUser to the onTextChange javascript. The timeout is very nice because it allows for typing without causing postbacks until the typer stops typing for that many milliseconds.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/xml-script&quot;</span><span class="kwrd">&gt;</span>
 &lt;page&gt;
  &lt;components&gt;
   &lt;textbox id=<span class="str">&quot;TextBoxSearchUser&quot;</span>&gt;
    &lt;behaviors&gt;
     &lt;textchangedbehavior timeout=<span class="str">&quot;100&quot;</span>
        changed=<span class="str">&quot;onTextChange&quot;</span> /&gt;
    &lt;/behaviors&gt;
   &lt;/textbox&gt;
  &lt;/components&gt;
 &lt;/page&gt;
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p></p>
<h1>Conclusions</h1>
<p>AJAX, though in concept is not new, is one of the most exciting new technologies to hit the Web for quite some time. The tool kits now available, such as Microsoft&#8217;s Atlas which is described here and included with the demonstration download, makes adding AJAX functionality to existing ASP.NET 2.0 applications very straight forward. In this article, I&#8217;ve discussed the mechanics of adding AJAX functionality but have not addressed the impact to web servers, cross browser functionality or web design. Those things must all be considered before including AJAX technology in an existing web application. Overall however, AJAX, and Microsoft&#8217;s implementation ATLAS, are wonderful things.</p>
]]></content:encoded>
			<wfw:commentRss>http://peterkellner.net/2006/03/02/ajaxmeetsaspnet20/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Microsoft ASP.NET 2.0 Member/Role Management with IISPart 2: Implementation</title>
		<link>http://peterkellner.net/2006/01/09/microsoft-aspnet-20-memberrole-management-with-iis/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=microsoft-aspnet-20-memberrole-management-with-iis</link>
		<comments>http://peterkellner.net/2006/01/09/microsoft-aspnet-20-memberrole-management-with-iis/#comments</comments>
		<pubDate>Mon, 09 Jan 2006 19:27:24 +0000</pubDate>
		<dc:creator>Peter Kellner</dc:creator>
				<category><![CDATA[.Net 2.0]]></category>
		<category><![CDATA[ASP.NET 2.0]]></category>
		<category><![CDATA[MSDN Articles]]></category>

		<guid isPermaLink="false">http://peterkellner.net/?p=24</guid>
		<description><![CDATA[<p>With the release of Microsoft Visual Studio 2005, there is no "out of the box" solution for maintaining the Membership and Role databases in Microsoft IIS. This is a problem when you move your application from development to a production IIS server. The utility that Microsoft provides, ASP.NET Web Configuration, can be run only in a development, non-production environment. This article and its associated code solve this by implementing a three-tier solution to Member and Role management while using standard Microsoft ASP.NET tools. This means that it will run in any ASP.NET 2.0 environment, including IIS. The solution is flexible and very easy to add to any existing ASP.NET 2.0 website project.</p>]]></description>
			<content:encoded><![CDATA[<p class="style3">Also published on Microsoft&#8217;s MSDN Network at <a title="http://msdn2.microsoft.com/en-us/library/aa478947.aspx" href="http://msdn2.microsoft.com/en-us/library/aa478947.aspx">http://msdn2.microsoft.com/en-us/library/aa478947.aspx</a></p>
<p class="style3"><a href="http://peterkellner.net/FilesForWebDownload/Downloads_604C/MembershipEditor7.zip">Click Here for Source Code Associated With This Article </a></p>
<p> Applies to:   <br /> 
<ul>
<li>Microsoft ASP.NET 2.0 </li>
<li>Microsoft Visual Studio 2005 </li>
<li>Microsoft Internet Information Services </li>
</ul>
<p> <span id="more-14"></span>
<p class="style3"><a href="http://peterkellner.net/2006/01/08/microsoft-aspnet-20-memberrole-management-with-iis-part-1-security-and-configuration-overview/">Link To Part 1: Security and Configuration</a></p>
<h2>Contents</h2>
<p> <a href="#asp2memroleman_topic1">Introduction</a>   <br /><a href="#asp2memroleman_topic2">Technologies Used</a>   <br /><a href="#asp2memroleman_topic3">The Application and Project</a>   <br /><a href="#asp2memroleman_topic4">The ObjectDataSource in Detail</a>   <br /><a href="#asp2memroleman_topic5">The Return Value of the Select Method (Type Collection)</a>   <br /><a href="#asp2memroleman_topic6">The Select Method Itself</a>   <br /><a href="#asp2memroleman_topic7">The Custom Sort Criteria</a>   <br /><a href="#asp2memroleman_topic8">ObjectDataSource In GridView (Data Control)</a>   <br /><a href="#asp2memroleman_topic9">Conclusion</a>   </p>
<h2 id="aspmemmansec_topic1">Introduction</h2>
<p><a href="http://peterkellner.net/images/MSDN_Membership/membiis_fig01L.gif" target="_top"><img border="0" alt="Click here for larger image" src="http://peterkellner.net/images/MSDN_Membership/membiis_fig01S.gif" /></a></p>
<p><strong>Figure 1. Membership Editor</strong></p>
<p>With the release of Microsoft Visual Studio 2005, there is no &quot;out of the box&quot; solution for maintaining the Membership and Role databases in Microsoft IIS. This is a problem when you move your application from development to a production IIS server. The utility that Microsoft provides, ASP.NET Web Configuration, can be run only in a development, non-production environment. This article and its associated code solve this by implementing a three-tier solution to Member and Role management while using standard Microsoft ASP.NET tools. This means that it will run in any ASP.NET 2.0 environment, including IIS. The solution is flexible and very easy to add to any existing ASP.NET 2.0 website project.</p>
<p>The tiers of this solution are defined as follows. The first tier, the ASP.NET page (also known as the presentation layer), interfaces with two business objects through the object data source. These business objects function as the middle tier, and they are wrappers for members and roles. The third tier, or back end, consists of the Membership and Role Manager APIs provided by ASP.NET. The middle tier objects can easily be dropped into any ASP.NET 2.0 project and used directly, with almost no changes.</p>
<p>This article explains in depth the implementation of the middle tier—that is, the data objects, as well as the ObjectDataSource that is associated with them. It then explains how to use these objects in an ASP.NET Web project that uses Microsoft SQL Server Express 2005, which comes bundled with Visual Studio 2005. However, the Membership API provided by Microsoft uses their provider technology; therefore, the solution presented here is database independent. Membership and role information could just as easily come from LDAP, SQL Server, or Oracle.</p>
<h2 id="asp2memroleman_topic2">Technologies Used</h2>
<h3>The ObjectDataSource</h3>
<p>There are two ObjectDataSource instances defined. One is for Membership Data (User Names, Creation Date, Approval, and so on), and the other is for Roles (Administrator, Friends, and so on). Both of these data sources are completely populated with all of the data access methods—that is, they both have Member functions that perform inserts, updates, deletes, and selects. Both ObjectDataSource instances return a Generic List type, which means that in the GridView, the column names are automatically set to the property value names of the ObjectDataSource. In addition, custom sorting is implemented so that users can click the column headers in the GridView in order to sort the data forwards or backwards, as desired.</p>
<h3>SQL Server Express 2005 and Web.Config</h3>
<p>The data provider source for the Membership and Role databases is SQL Server Express 2005. The appropriate entries are set in the web.config file in order to make this happen. A short discussion is given later in this article of how to set up a new project from scratch. The connection string for SQL Server Express 2005 is not mentioned in the web.config file, because it is already defined in the Machine.Config file that is included as a default part of the Microsoft .NET 2.0 Framework.</p>
<h3>IIS (5.1 and 6.0) Compatible</h3>
<p>The Web server can be either version 5.1 or 6.0. In order to do any testing of multiple users logged in to your Web app, you must use IIS. The built-in development Web server does not correctly maintain state of the different users who are logged in. Although the Asp.net Web config tool could be made to work with IIS, the additional security work necessary in order to enable this was not done.</p>
<h3>The GridView Control</h3>
<p>The GridView is used to present the data for both membership and roles. As mentioned earlier, because of the use of a Generic type for the ObjectDataSource, the column names of the GridView are automatically named after the property values of the ObjectDataSource. Without the use of Generics, the column names revert to meaningless default values and must each be edited by hand.</p>
<h2 id="asp2memroleman_topic3">The Application and Project</h2>
<p>The project necessary in order to run this utility is very simple and self-contained. The project files, which are available for download, contain a full working example. Because there is no direct database access to the users and roles, all that is needed is to grab the three data objects (<strong>MembershipDataObject.cs</strong>, <strong>MembershipUserSortable.cs</strong> and <strong>RoleDataObject.cs</strong>: see Figure 2).</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig02.gif" width="330" height="339" /></p>
<p><strong>Figure 2. Membership Editor project</strong></p>
<p>In the SamplePages folder there are several other samples that demonstrate the use of the previously mentioned modules. As one example, Membership.aspx is the example shown in Figure 1. It can be used for selecting, updating, inserting, and deleting Members and Roles, as well as for assigning roles to members.</p>
<p>With a working ASP.NET 2.0 application that already has a working membership module, these pages should need no external configuration beyond what has already been done. These files can be copied directly into a project and they will just work.</p>
<p>If this is the first implementation of Membership and Role Management in an application, the process to follow to create a solution using these objects is as follows:</p>
<ol type="1">
<li>Using Visual Studio 2005, create a new Web project of the type ASP.NET Web Site. </li>
<li>Click <strong>Website / ASP.NET Configuration</strong> on the menu. </li>
<li>Follow the wizard steps (1 to 7) to create some sample users and roles. This will effectively create a valid web.config file in the current project that has enough information to have Member Management up and running. By default, it will use SQL Server Express 2005 in its default configuration. </li>
<li>Include the three .cs files in the project, and then include the sample .aspx pages as samples. </li>
</ol>
<h2 id="asp2memroleman_topic4">The ObjectDataSource in Detail</h2>
<p>The ObjectDataSource technology enables the creation of a datasource that behaves very similarly to the SqlDataSource—that is, it exposes interfaces that allow for selecting, updating, inserting, and deleting records (or record-like objects) from a persistent data store (such as a database). The next several sections of this article will discuss the object (or class file) that the ObjectDataSource uses to manipulate membership. Its name in the project is <strong>MembershipUserODS.cs</strong>.</p>
<h3>The Class (MembershipUserODS)</h3>
<p>Because the data is retrieved from the Microsoft Membership API, an ObjectDataSource is used to solve the problem. The first step in doing this is to create a stand-alone class that wraps <strong>MembershipUser</strong> so that it can be associated with the ObjectDataSource. The example below shows a typical set of methods that need to be implemented, and the next several sections of this article will discuss the implementation of each member function. Many of the details are left out of the article, but they are included in the source code provided with this article. </p>
<p> 
<pre class="csharpcode">[DataObject(<span class="kwrd">true</span>)
<span class="kwrd">public</span> <span class="kwrd">class</span> MembershipUserWrapper {
  [DataObjectMethod(DataObjectMethodType.Select, <span class="kwrd">true</span>)]
  <span class="kwrd">static</span> <span class="kwrd">public</span> Collection&lt;membershipuserwrapper&gt; GetMembers(<span class="kwrd">string</span>
       sortData) {
    <span class="kwrd">return</span> GetMembers(<span class="kwrd">true</span>, <span class="kwrd">true</span>, <span class="kwrd">null</span>, sortData);
  }

  [DataObjectMethod(DataObjectMethodType.Insert, <span class="kwrd">true</span>)]
  <span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Insert(<span class="kwrd">string</span> UserName, <span class="kwrd">bool</span> isApproved,
<span class="kwrd">string</span> comment, DateTime lastLockoutDate, ...) {
  }

  [DataObjectMethod(DataObjectMethodType.Delete, <span class="kwrd">true</span>)]
  <span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Delete(<span class="kwrd">object</span> UserName, <span class="kwrd">string</span> Original_UserName){
    Membership.DeleteUser(Original_UserName, <span class="kwrd">true</span>);
  }

  [DataObjectMethod(DataObjectMethodType.Update, <span class="kwrd">true</span>)]
  <span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Update(<span class="kwrd">string</span> original_UserName,<span class="kwrd">string</span> email,...){
  }
}
&lt;/membershipuserwrapper&gt;</pre>
<p></p>
<h3>The Class Declaration</h3>
<p>The class declaration shown above is special because of the attribute <strong>[(DataObject(true)]</strong>. This attribute tells the the Visual Studio 2005 ObjectDataSource Creation Wizard to look only for members with this special attribute when searching for DataObjects in the data class. See the example in the section showing where this class is assigned to a GridView component.</p>
<h3>The Insert Method</h3>
<p>The details of each section involve a very straightforward use of the Membership API provided by Microsoft. For example, here is what might be a typical <strong>Insert </strong>method in more detail. </p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Insert,<span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Insert(<span class="kwrd">string</span> userName, <span class="kwrd">string</span> password,)
{
   MembershipCreateStatus status;
      Membership.CreateUser(userName, password,);
}</pre>
<p></p>
<p>This class <strong>Insert</strong> is polymorphic, which means there can be multiple <strong>Insert</strong> methods used for different purposes. For example, it may be necessary to dynamically decide whether a created user should be approved depending on the circumstances. For example, a new user created in an admin screen may want to create users defaulted to approved, whereas a user register screen might default to not approved. To do this, another <strong>Insert</strong> method is needed, with an additional parameter. Here is what an <strong>Insert</strong> method that would achieve this goal might look like. </p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Insert,<span class="kwrd">false</span>)]
<span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Insert(<span class="kwrd">string</span> userName, <span class="kwrd">string</span> password, <span class="kwrd">bool</span> isApproved)
{
MembershipCreateStatus status;
   Membership.CreateUser(UserName, password,
      isApproved, <span class="kwrd">out</span> status);
}</pre>
<p></p>
<p>As with the other methods listed here, the examples shown are not what will actually be found in the accompanying source. The examples here are meant to be illustrations of typical uses. More complete and commented uses are included in the source.</p>
<h3>The Update Method</h3>
<p>The <strong>Update</strong> method is a very straightforward implementation of the Membership API. Just like the <strong>Insert</strong> method, there can be multiple implementations of <strong>Update</strong>. Only one implementation is shown here. In the code available for download, there are more polymorphic implementations of <strong>Update</strong>, including one that just sets the <strong>IsApproved</strong> property (shown in the following example).</p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Update,<span class="kwrd">false</span>)]
<span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Update(<span class="kwrd">string</span> UserName,<span class="kwrd">bool</span> isApproved)
{
   <span class="kwrd">bool</span> dirtyFlag = <span class="kwrd">false</span>;
   MembershipUser mu = Membership.GetUser(UserName);
   <span class="kwrd">if</span> (mu.isApproved != isApproved)
   {
      dirtyFlag = <span class="kwrd">true</span>;
      mu.IsApproved = isApproved;
   }
   <span class="kwrd">if</span> (dirtyFlag == <span class="kwrd">true</span>)
   {
      Membership.UpdateUser(mu);
   }
}</pre>
<p></p>
<h3>The Delete Method</h3>
<p><font face="verdana">The <strong>Delete</strong> method is the simplest, and it takes one parameters, <strong>UserName</strong>.</font></p>
<p></p>
<pre class="csharpcode">&lt;h2&gt;The Delete Method&lt;/h2&gt;
<span class="kwrd">static</span> <span class="kwrd">public</span> <span class="kwrd">void</span> Delete(<span class="kwrd">string</span> UserName)
{
   Membership.DeleteUser(UserName,<span class="kwrd">true</span>);
}</pre>
<p></p>
<h3>The Select Method with a Sort Attribute</h3>
<p>The <strong>Select</strong> method—<strong>GetMembers</strong>, in this case—has multiple components, each of them worthy of discussion. First, what it returns is discussed, and then the actual method itself, and finally, how it sorts what it returns.</p>
<h2 id="asp2memroleman_topic5">The Return Value of the Select Method (Type Collection)</h2>
<p>The return value of the <strong>Select</strong> method (which also is referred to as <strong>Get</strong>) is a Generic Collection class. Generics are used because the ObjectDataSource ultimately associated with the class uses reflection to determine the column names and types. These names and types are associated with each row of data that is returned. This is the same way that a SqlDataSource uses the database metadata of a table or stored procedure to determine the column names of each row. Since the return type of the <strong>Select</strong> method is MembershipUserWrapper, which inherits from MembershipUser, most of the properties of this class are the same properties that are associated with MembershipUser. Those properties include:</p>
<ul type="disc">
<li><strong>ProviderUserKey </strong></li>
<li><strong>UserName </strong></li>
<li><strong>LastLockoutDate </strong></li>
<li><strong>CreationDate </strong></li>
<li><strong>PasswordQuestion </strong></li>
<li><strong>LastActivityDate </strong></li>
<li><strong>ProviderName </strong></li>
<li><strong>IsLockedOut </strong></li>
<li><strong>Email </strong></li>
<li><strong>LastLoginDate </strong></li>
<li><strong>IsOnline </strong></li>
<li><strong>LastPasswordChangedDate </strong></li>
<li><strong>Comment </strong></li>
</ul>
<p>Jumping ahead of ourselves a little, one very nice feature of property values is that they can be Read-only (no set method), Write-only (no read method), and of course, Read/Write. The ObjectDataSource Wizard recognizes this and builds the appropriate parameters so that when the datacontrol is rendered (using the ObjectDataSource), just the fields that are updatable (read/write) are enabled for editing. This means that you can not change the <strong>UserName</strong> property, for example. If this does not make sense now, it will later, when we discuss the ObjectDataSource and the data components in more detail.</p>
<h2 id="asp2memroleman_topic6">The Select Method Itself</h2>
<p>Just like <strong>Insert</strong> and <strong>Update</strong>, the <strong>Select</strong> method is polymorphic. There can be as many different <strong>Select</strong> methods as there are different scenarios. For example, it may be desiable to use the <strong>Select</strong> method to select users based on whether they are approved, not approved, or both. Typically, there is one <strong>Get</strong> method that has the most possible parameters associated with it, and the other <strong>Get</strong> methods call it. In our case, there are three <strong>Get</strong> methods: one to retrieve all records, one to retrieve based on approval, and one to retrieve an individual record based on a select string. In the following example, the method that returns all users is being called. By setting both Booleans to <strong>true</strong>, all users will be returned. </p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Select, <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">public</span> List&lt;membershipdata&gt; GetMembers(<span class="kwrd">string</span> sortData)
{
   <span class="kwrd">return</span> GetMembers(<span class="kwrd">true</span>,<span class="kwrd">true</span>,<span class="kwrd">null</span>,<span class="kwrd">null</span>);
}
&lt;/membershipdata&gt;</pre>
<p></p>
<p>The next example shows a more detailed <strong>Get</strong> method. This example shows only the beginning of the method. The details of the method not shown include finishing the property assignments, filtering for approval status and rejecting the records not meeting the criteria, and applying the sort criteria. Following this example is more discussion about the sort criteria. (Note that calling <strong>GetAllUsers</strong> on a database with more than a few hundred users [the low hundreds] is quickly going to become an expensive operation.)</p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Select, <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">public</span> List&lt;membershipdata&gt; GetMembers(<span class="kwrd">bool</span> AllApprUsers,
    <span class="kwrd">bool</span> AllNotApprUsers, <span class="kwrd">string</span> UserToFind, <span class="kwrd">string</span> sortData)
{
   List&lt;/membershipdata&gt;&lt;membershipdata&gt; memberList = <span class="kwrd">new</span> List&lt;/membershipdata&gt;&lt;membershipdata&gt;();
   MembershipUserCollection muc = Membership.GetAllUsers();
   <span class="kwrd">foreach</span> (MembershipUser mu <span class="kwrd">in</span> muc)
   {
      MembershipData md = <span class="kwrd">new</span> MembershipData();
      md.Comment = mu.Comment;
      md.CreationDate = mu.CreationDate;
&lt;/membershipdata&gt;</pre>
<p></p>
<h2 id="aspmemmansec_topic7">The Custom Sort Criteria<a id="aspmemmansec_topic7" name="aspmemmansec_topic7"></a></h2>
<p>Notice that, in the preceding code, a parameter string named <strong>sortData</strong> is passed into <strong>GetMembers</strong>. If, in the ObjectDataSource declaration, a <strong>SortParameterName</strong> is specified as one of its attributes, this parameter will be passed automatically to all <strong>Select</strong> methods. Its value will be the name specified by the attribute <strong>SortExpression</strong> in the column of the datacontrol. In our case, the datacontrol is the GridView.</p>
<p>The <strong>Comparer</strong> method is invoked based on the parameter <strong>sortName</strong> coming into the <strong>GetMembers</strong> method. Since these ASP.NET Web pages are stateless, we have to assume that the direction of the current sort (either forward or backwards) is stored in the viewstate. Each call reverses the direction of the previous call. That is, it toggles between forward sort and reverse sort as the user clicks the column header.</p>
<p>Assuming that a GridView is used, the parameter that gets passed into <strong>GetMembers(sortData)</strong> has in it the data from the <strong>SortExpression</strong> attribute of the GridView column. If a request for sorting backwards is being made, the word &quot;DESC&quot; is appended to the end of the sort string. So, for example, the first time the user clicks on the column Email, the <strong>sortData</strong> passed into <strong>GetMembers</strong> is &quot;Email.&quot; The second time the user clicks on that column, the parameter <strong>sortData</strong> becomes &quot;Email DESC,&quot; then &quot;Email,&quot; then &quot;Email DESC,&quot; and so on. As a special note, the first time the page is loaded, the <strong>sortData</strong> parameter is passed in as a zero-length string (not null). Below is the guts of the <strong>GetMembers</strong> method that retrieves and sorts the data so that it is returned in the correct order.</p>
<p></p>
<pre class="csharpcode">[DataObjectMethod(DataObjectMethodType.Select, <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">public</span> List&lt;membershipdata&gt; GetMembers(<span class="kwrd">string</span> sortData)
{
  List&lt;/membershipdata&gt;&lt;membershipdata&gt; memberList = <span class="kwrd">new</span> List&lt;/membershipdata&gt;&lt;membershipdata&gt;();
  MembershipUserCollection muc = Membership.GetAllUsers();
  List&lt;membershipuser&gt; memberList = <span class="kwrd">new</span> List&lt;/membershipuser&gt;&lt;membershipuser&gt;(muc);

  <span class="kwrd">foreach</span> (MembershipUser mu <span class="kwrd">in</span> muc)
  {
    MembershipData md = <span class="kwrd">new</span> MembershipData(mu);
    memberList.Add(md);
  }

  ... Code that implements Comparison

  â�¦ memberList.Sort(comparison);

  <span class="kwrd">return</span> memberList;
}
&lt;/membershipuser&gt;&lt;/membershipdata&gt;</pre>
<p></p>
<p>In the next section, when this is incorporated into a GridView, it will become more clear.</p>
<h3>The ObjectDataSource Declaration </h3>
<p>The easiest way to declare an ObjectDataSource is to drag and drop one from the datacontrols on the toolbar, after first creating an empty ASP.NET page with the Visual Studio 2005 wizard. After creating the ObjectDataSource, a little tag in the upper-right corner of the newly created ObjectDataSource can be grabbed; then, clicking <strong>Configure Data Source</strong> opens a wizard saying &quot;Configure Data Source—ObjectDataSource1&quot; (see Figure 3).</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig03.gif" width="450" height="354" /></p>
<p><strong>Figure 3. Configuring ObjectDataSource</strong></p>
<p>At this point, two classes that are available for associating with an ObjectDataSource will be seen. <strong>MembershipUserODS</strong> is the primary subject of this article. <strong>RoleDataObject</strong> is basically the same thing, but it encapsulates Membership Roles. Also, remember that what is shown here are just the objects that are declared with the special class attribute <strong>[DataObject(true)]</strong> that was described in &quot;The Class Definition.&quot;</p>
<p>After choosing <strong>MembershipUserODS</strong>, a dialog box with four tabs appears. The methods to be called from the <strong>MembershipUserODS</strong> class will be defined on these tabs. Methods for <strong>Select</strong>, <strong>Update</strong>, <strong>Insert</strong>, and <strong>Delete</strong> will be associated with member functions in the <strong>MembershipUserODS</strong>. In many cases, there will be multiple methods available in the class for each of these. The appropriate one must be chosen, based on the data scenario desired. All four tabs are shown in Figure 4. By default, the members that are marked with the special attribute <strong>[DataObjectMethod(DataObjectMethodType.Select, false)]</strong> will be populated on the tabs. Of course, however, this particular attribute is the default for <strong>Select</strong>. Changing the expression <strong>DataObjectMethodType.Select</strong> to <strong>DataObjectMethodType.Insert</strong>, <strong>DataObjectMethodType.Update</strong>, and <strong>DataObjectMethodType.Delete</strong> will make the defaults appropriate for the different tabs. The second parameter, a Boolean, signifies that this method (remembering that it may be defined polymorphically) is the default method, and that it should be used in the tab control.</p>
<h3>The Select Method</h3>
<p>As mentioned earlier, in the section describing the <strong>MembershipUserODS</strong> class, the <strong>GetMembers</strong> function returns a Generic Collection class. This enables the <strong>ObjectDataSourceMembershipUser</strong> control defined here to use reflection and ascertain the calling parameters associated with this <strong>GetMembers</strong> call. In this case, the parameters used to call <strong>GetMembers</strong> are <strong>returnAllApprovedUsers</strong>, <strong>returnAllNotApprovedUsers</strong>, <strong>userNameToFind</strong>, and <strong>sortData</strong>. Based on this, the actual definition of the new ObjectDataSource will be as follows.</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig04.gif" /></p>
<p><strong>Figure 4. Assigning the Select method</strong> </p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:ObjectDataSource</span> <span class="attr">ID</span><span class="kwrd">=&quot;ObjectDataSourceMembershipUser&quot;</span><span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span>
    <span class="attr">SelectMethod</span><span class="kwrd">=&quot;GetMembers&quot;</span><span class="attr">UpdateMethod</span><span class="kwrd">=&quot;GetMembers&quot;</span>
    <span class="attr">SortParameterName</span><span class="kwrd">=&quot;SortData&quot;</span>
    <span class="attr">TypeName</span><span class="kwrd">=&quot;MembershipUtilities.MembershipDataObject&quot;</span>
    <span class="attr">DeleteMethod</span><span class="kwrd">=&quot;Delete&quot;</span> <span class="attr">InsertMethod</span><span class="kwrd">=&quot;Insert&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">insertparameters</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;userName&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;String&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;password&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;String&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;isApproved&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;Boolean&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">insertparameters</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">asp</span><span class="kwrd">&gt;</span></pre>
<p></p>
<h3>The Insert Method</h3>
<p>The <strong>Insert</strong> method, in this case, is assigned to the member function <strong>Insert()</strong>. Notice that this method is called with only two parameters: <strong>UserName</strong> and <strong>Password</strong> (see Figure 5). The number of parameters must equal the number of parameters declared in the ObjectDataSource. The parameter declaration from the ObjectDataSource is shown below. There is a second <strong>Insert Member</strong> function defined that adds a third parameter: <strong>approvalStatus</strong>. If the functionality of this ObjectDataSource is to include inserting while setting the <strong>approvalStatus</strong>, then the other insert method should be chosen from the drop-down list. That would cause the following InsertParameters to be inserted into your .aspx page. If the one with two parameters is chosen, the block would not include the <strong>asp:Parameter</strong> with the name <strong>isApproved</strong> in it. Again, keep in mind that this example may not agree with the source code enclosed, and that it is here only as an example. The source enclosed is much more complete.</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig05.gif" /></p>
<p><strong>Figure 5. Assigning the Insert method</strong> </p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:ObjectDataSource</span> <span class="attr">ID</span><span class="kwrd">=&quot;ObjectDataSourceMembershipUser&quot;</span><span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span>
    <span class="attr">SelectMethod</span><span class="kwrd">=&quot;GetMembers&quot;</span><span class="attr">UpdateMethod</span><span class="kwrd">=&quot;GetMembers&quot;</span>
    <span class="attr">SortParameterName</span><span class="kwrd">=&quot;SortData&quot;</span>
    <span class="attr">TypeName</span><span class="kwrd">=&quot;MembershipUtilities.MembershipDataObject&quot;</span>
    <span class="attr">DeleteMethod</span><span class="kwrd">=&quot;Delete&quot;</span> <span class="attr">InsertMethod</span><span class="kwrd">=&quot;Insert&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">insertparameters</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;userName&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;String&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;password&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;String&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;isApproved&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;Boolean&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">insertparameters</span><span class="kwrd">&gt;</span>
    ...
<span class="kwrd">&lt;/</span><span class="html">asp</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>Also, keep in mind that using an <strong>Insert</strong> method with minimal parameters will require a default password to be set in the method. In a production system, this would be a bad idea. See the attached source code for a better example of how to handle inserts. Specifically, see the page Membership.aspx for this functionality.</p>
<h2>The Update Method</h2>
<p>The <strong>Update</strong> method, in this case, is assigned to the member function <strong>Update()</strong>. Notice that this method is called with multiple parameters: <strong>UserName</strong>, <strong>Email</strong>, <strong>isApproved</strong>, and <strong>Comment</strong> (see Figure 6). In addition, there is another <strong>Update</strong> method that has all the updatable parameters. This is useful for creating a control that has the most possible update capabilities. Just like <strong>Insert</strong>, the appropriate <strong>Update</strong> method is chosen for this ObjectDataSource. When the wizard is finished, it will automatically create UpdateParameters, as shown below.</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig06.gif" /></p>
<p><strong>Figure 6. Assigning the Update method</strong></p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">asp:ObjectDataSource</span> <span class="attr">ID</span><span class="kwrd">=&quot;ObjectDataSourceMembershipUser&quot;</span><span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span>
    <span class="attr">SelectMethod</span><span class="kwrd">=&quot;GetMembers&quot;</span> <span class="attr">InsertMethod</span><span class="kwrd">=&quot;Insert&quot;</span>
    <span class="attr">SortParameterName</span><span class="kwrd">=&quot;SortData&quot;</span>
    <span class="attr">TypeName</span><span class="kwrd">=&quot;MembershipUtilities.MembershipUserODS&quot;</span>
    <span class="attr">UpdateMethod</span><span class="kwrd">=&quot;Update&quot;</span> <span class="attr">DeleteMethod</span><span class="kwrd">=&quot;Delete&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">updateparameters</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;Original_UserName&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;email&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;String&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;isApproved&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;Boolean&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;comment&quot;</span> <span class="attr">Type</span><span class="kwrd">=&quot;String&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">updateparameters</span><span class="kwrd">&gt;</span>
    ...
    ...</pre>
<p></p>
<h3>The Delete Method</h3>
<p>The <strong>Delete</strong> method, in this case, is assigned to the member function <strong>Delete()</strong>. There is, of course, only one <strong>Delete</strong> method necessary (see Figure 7). Below is the declaration of the ObjectDataSource that supports this <strong>Delete</strong> method.</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig07.gif" /></p>
<p><strong>Figure 7. Assigning the Delete method</strong></p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">asp:ObjectDataSource</span> <span class="attr">ID</span><span class="kwrd">=&quot;ObjectDataSource1&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span>
    <span class="attr">SelectMethod</span><span class="kwrd">=&quot;GetMembers&quot;</span> <span class="attr">InsertMethod</span><span class="kwrd">=&quot;Insert&quot;</span>
    <span class="attr">SortParameterName</span><span class="kwrd">=&quot;SortData&quot;</span>
    <span class="attr">TypeName</span><span class="kwrd">=&quot;MembershipUtilities.MembershipUserODS&quot;</span>
    <span class="attr">UpdateMethod</span><span class="kwrd">=&quot;Update&quot;</span> <span class="attr">DeleteMethod</span><span class="kwrd">=&quot;Delete&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">deleteparameters</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </span> <span class="attr">arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;UserName&quot;</span> <span class="kwrd">/&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr"> <img src='http://PetersBlogCDN.s3.amazonaws.com/wp/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </span> <span class="attr">arameter</span> <span class="attr">Name</span><span class="kwrd">=&quot;Original_UserName&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">deleteparameters</span><span class="kwrd">&gt;</span>
    ...</pre>
<p></p>
<h3>The Class (RoleDataObject)</h3>
<p>Just like Membership, Roles are set up with their own DataObject. Since there is nothing special about Roles, there are no details regarding their setup in this article. An understanding of how the Membership DataObjects are set up is transferable to how Roles are set up. In Membership, the Microsoft C# object that encapsulates the Membership API is <strong>MembershipDataObject.cs</strong>. The analogous class for encapsulating the Role API is <strong>RoleDataObject.cs</strong>.</p>
<h2 id="asp2memroleman_topic8">ObjectDataSource In GridView (Data Control)</h2>
<p>Class declarations for Membership Users and Roles have been established in the previous sections of this article. Also, a complete <strong>ObjectDataSource</strong> object has been placed on an ASP.NET page. The final step is to create the user interface, also known as the user-facing tier of the application or the presentation layer. Because so much of the work is done by the objects created, all that is necessary is to create a simple GridView and associate it with the ObjectDataSource. The steps are as follows:</p>
<ol type="1">
<li>In visual mode of the ASP.NET page designer, drag and drop the GridView data component onto the page associated with the ObjectDataSource created earlier. </li>
<li>Enable selecting, deleting, updating, inserting, and sorting. </li>
</ol>
<p>Figure 8 shows the dialog box associated with configuring the Gridview.</p>
<p><img src="http://peterkellner.net/images/MSDN_Membership/membiis_fig08.gif" /></p>
<p><strong>Figure 8. Configuring GridView</strong></p>
<p>A special mention should be made here that <strong>DataKeyNames</strong> in the <strong>GridView</strong> control shown below is automatically set. This is because the primary key has been tagged in the <strong>MembershipUserSortable</strong> class with the attribute <strong>[DataObjectField(true)]</strong><code>,</code> as shown below. Notice also that since <strong>UserName</strong> is a property of the <strong>MembershipUser</strong> class, it was necessary to provide a default property in the class extending <strong>MembershipUser</strong>. Since this is a Read-only property, only a <strong>Get</strong> method is declared. (<strong>UserName</strong> is public virtual on <strong>MembershipUser</strong>.)</p>
<pre>[DataObjectField(true)]
public override string UserName {
  get { return base.UserName;
}</pre>
<p>There is one attribute in the GridView that must be set by hand: the primary key must be set in the control. To do this, associate the attribute <strong>DataKeyName</strong> with <strong>UserName</strong>. The GridView declaration is shown below.</p>
<pre>&lt;asp:GridView ID=&quot;GridView1&quot; DataKeyNames=&quot;UserName&quot; runat=&quot;server&quot;
        AllowPaging=&quot;True&quot; AutoGenerateColumns=&quot;False&quot;
        DataSourceID=&quot;ObjectDataSourceMembershipUser&quot;
        AllowSorting=&quot;True&quot;&gt;
    &lt;Columns&gt;
    ...
    ...</pre>
<h2 id="asp2memroleman_topic9">Conclusion</h2>
<p>To wrap things up, you should now be familiar with how to build your own three-tier architected ASP.NET application. In addition, you now have two objects that you can freely use that encapsulate Members and Roles. You could now, for example, use the <strong>DetailView</strong> control, and in only a few minutes build a complete DetailView interface to Members that performs Navigation, Inserting, Updating, and Deleting of Members. Give it a try!</p>
<p>I have specifically not gone into the implementations of adding, updating, and deleting Members or Roles. If you look at the source code, you will find that I have used the APIs in a very straightforward way. Not much will be gained by describing those calls in much detail here, because I&#8217;m sure that if you are still reading this, you, like me, are probably learning this material as you go.</p>
<p>I was fortunate enough to be at MS TechEd in Orlando and PDC in LA this year, and was able to ask many questions of the ASP.NET team. In particular, I would like to thank Brad Millington and Stefan Schackow for putting up with my many questions during those weeks, and Jeff King and Brian Goldfarb for all their help in making this a better article. In some way, this article is payback, so that hopefully they won&#8217;t have to answer as many questions in the future.</p>
<p><a href="http://peterkellner.net/download-manager/"></a></p>
</p>
<hr />
<p><strong>About the author</strong> </p>
<p>Peter Kellner founded 73rd Street Associates in 1990, where he successfully delivered systems for university clinic scheduling, insurance company management, and turnkey physician office management to more than 500 customers nationwide. Ten years later, in 2000, 73rd Street Associates was purchased by a large insurance company, and Peter started a new career as an independent software consultant. Among the technologies he currently is involved with are ASP.NET, Oracle, Java, VOiP, and soon, SQL Server. When not working, Peter spends most his free time biking. He has ridden his bike across the globe. Most recently he and his wife, Tammy, rode across the U.S., from California to Georgia, in just 27 days.</p>
<p>His blog site is <a href="http://peterkellner.net/">http://peterkellner.net</a>. You will find this article and the code posted in the download section.</p>
]]></content:encoded>
			<wfw:commentRss>http://peterkellner.net/2006/01/09/microsoft-aspnet-20-memberrole-management-with-iis/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>Microsoft ASP.NET 2.0 Member/Role Management with IISPart 1: Security and Configuration Overview</title>
		<link>http://peterkellner.net/2006/01/08/microsoft-aspnet-20-memberrole-management-with-iis-part-1-security-and-configuration-overview/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=microsoft-aspnet-20-memberrole-management-with-iis-part-1-security-and-configuration-overview</link>
		<comments>http://peterkellner.net/2006/01/08/microsoft-aspnet-20-memberrole-management-with-iis-part-1-security-and-configuration-overview/#comments</comments>
		<pubDate>Sun, 08 Jan 2006 22:07:10 +0000</pubDate>
		<dc:creator>Peter Kellner</dc:creator>
				<category><![CDATA[.Net 2.0]]></category>
		<category><![CDATA[ASP.NET 2.0]]></category>
		<category><![CDATA[MSDN Articles]]></category>

		<guid isPermaLink="false">http://peterkellner.net/?p=23</guid>
		<description><![CDATA[<p>This article is the first of two articles describing the secure use and setup   of a three tier solution for managing ASP.NET Membership and Roles. This first   article will focus on configuring, using, and, most importantly, securing this   solution, as well as providing an overview of how it can be implemented in a   typical Microsoft ASP.NET 2.0 Web solution. The <strong>Membership</strong> and <strong>Roles</strong> objects will be treated as working without delving into their   internal structures. Managing Members and Roles will seem no different than   managing data from a simple data source. In the second article, the internals of   these controls and objects will be explained in enough detail so developers   would be able to build their own using similar techniques.</p>]]></description>
			<content:encoded><![CDATA[<p><font size="4"><strong>Also published on Microsoft&#8217;s MSDN Network at</strong></font></p>
<p class="style4"><a title="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASPMemManSec.asp" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASPMemManSec.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/ASPMemManSec.asp</a></p>
<p>Applies to:</p>
<ul>
<li>Microsoft ASP.NET 2.0 </li>
<li>Microsoft Visual Studio 2005 </li>
<li>Microsoft Internet Information Services  </ul>
<p> <span id="more-13"></span>
<p><a class="style3" href="http://peterkellner.net/archives/2006/01/09/24">Link To Part 2: Implementation</a></p>
<h4>Contents</h4>
<p><a href="#aspmemmansec_topic1" target="_self">Abstract</a>       <br /><a href="#aspmemmansec_topic2" target="_self">Introduction</a>       <br /><a href="#aspmemmansec_topic3" target="_self">Security Considerations</a>       <br /><a href="#aspmemmansec_topic4" target="_self">Role-Based Security in a ASP.NET 2.0 Web Site</a>       <br /><a href="#aspmemmansec_topic5" target="_self">Conclusion</a>       </p>
<p>   <a id="aspmemmansec_topic1" name="aspmemmansec_topic1"></a>
</p>
<h2>Abstract</h2>
</p>
<p>This article is the first of two articles describing the secure use and setup of a three tier solution for managing ASP.NET Membership and Roles. This first article will focus on configuring, using, and, most importantly, securing this solution, as well as providing an overview of how it can be implemented in a typical Microsoft ASP.NET 2.0 Web solution. The <strong>Membership</strong> and <strong>Roles</strong> objects will be treated as working without delving into their internal structures. Managing Members and Roles will seem no different than managing data from a simple data source. In the second article, the internals of these controls and objects will be explained in enough detail so developers would be able to build their own using similar techniques.</p>
<h2>Introduction</h2>
<p>ASP.NET 2.0 extends user authentication directly into the application programming domain. Using a standard .NET Library reference (<strong>system.web.security</strong>), developers can build full authentication into their application with very little extra work. With this in mind, it is important to remember that a certain level of due diligence is necessary to minimize the possibility that the application being built will not have its security compromised during use.</p>
<p>This article provides an overview of the security mechanisms and shows example security settings that are an essential part of creating a secure environment for Web applications. ASP.NET 2.0 provides many different configuration options that may or may not be deemed necessary, depending on security requirements. Throughout this article, the pros and cons of these configuration options will be discussed.</p>
<p>&#160;</p>
<h2>Security Considerations<a id="aspmemmansec_topic3" name="aspmemmansec_topic3"></a></h2>
</p>
<h3>Securing the Physical Environment</h3>
<p> It is often said that a computer&#8217;s security ends at the computer&#8217;s front panel power switch. No matter how well the system is secured from an OS level, physical protection is essential. It must be assumed that anyone who has physical access to the computer will always be able to compromise its integrity in one way or another.
</p>
<p>For further information on recommended best practices for securing a computer&#8217;s physical environment, please review <a href="http://www.microsoft.com/technet/archive/community/columns/security/5min/5min-203.mspx">this article</a> on Microsoft TechNet.</p>
</p>
<h3>Securing the Domain Environment</h3>
<p> Best practices for setting up user accounts, passwords, and privileges must be followed. If, for example, a user without privilege is able to directly access the database containing secure data used by the Web application, the application can become compromised.
</p>
<p>For further information on securing a computer&#8217;s domain environment, <a href="http://www.microsoft.com/security/default.mspx">the following articles</a> on the Microsoft Security Home Page give a lot of very helpful recommendations and tips.</p>
</p>
<h3>Securing the .NET Environment</h3>
<p> The .NET environment allows the setting of code access security. This means that individual system and application libraries can be associated with different trust levels. This can be very important in, for example, a shared hosting environment where multiple Web applications may be running. Each Web application that is potentially owned by different users may require isolation and protection from each other. In addition, without this isolation, each Web application could potentially impact critical system functions.
</p>
<p>In this article, it will be assumed that the ASP.NET user (the user that IIS runs on behalf of) is running with the highest trust level. This would likely be the case when a Web application is running in a dedicated environment. For further information on how code level security could be used to enhance the security of a Web server, see the MSDN article <a href="http://peterkellner.net/library/en-us/secmod/html/secmod82.asp">Using Code Access Security with ASP.NET</a>.</p>
<h3>ASP.NET&#8217;s Relationship with IIS</h3>
<p>ASP.NET supports three authentication providers when working with IIS: Forms Authentication, which uses application specific logic; Passport authentication, which is a centralized authentication service provided by Microsoft; and Windows authentication, which uses the authentication provided directly through IIS. The default authentication for ASP.NET projects, Forms Authentication, is used in this article. The authentication mode is specified in the web.config file. The syntax choices are as follows.</p>
<p> 
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">authentication</span> <span class="attr">mode</span> = <span class="kwrd">&quot;{Windows|Forms|Passport|None}&quot;</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">authentication</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p class="codelisting">The flow that is followed when a user logs in from a Web client is depicted in the flow chart in <a href="http://peterkellner.net/library/en-us/dnbda/html/authaspdotnet.asp">this article</a>.</p>
<p>Keep in mind that this article was written in 2001 and is current with the flow of IIS 5.1, not the currently shipping IIS 6.0 or later.</p>
<p><img alt="Security Flow between IIS and ASP.NET" src="http://peterkellner.net/images/MSDN_Membership/membsec_fig01.gif" /></p>
<p><strong>Figure 1. Security Flow between IIS and ASP.NET</strong></p>
</p>
<h2><a id="aspmemmansec_topic4" name="aspmemmansec_topic4"></a>Role-Based Security in an ASP.NET 2.0 Web Site</h2>
</p>
<h3>Initial Setup and Configuration</h3>
<p>Certain parameters that affect the overall running of an ASP.NET 2.0 Web application are set in the web.config file. Example parameters include a reference to the membership Provider (or database), the strength of the password required, and whether an e-mail is required to register. The relevant section of the web.config file is shown below with sample values for a minimalist security configuration. More details can be found by accessing Visual Studio 2005 help and looking up &quot;Membership Members.&quot; Each security parameter is explained there in detail.</p>
<p></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">providers</span><span class="kwrd">&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">remove</span> <span class="attr">name</span><span class="kwrd">=&quot;AspNetSqlMembershipProvider&quot;</span><span class="kwrd">/&gt;</span>
 <span class="kwrd">&lt;</span><span class="html">add</span> <span class="attr">name</span><span class="kwrd">=&quot;AspNetSqlMembershipProvider&quot;</span>
   <span class="attr">type</span><span class="kwrd">=&quot;System.Web.Security.SqlMembershipProvider,
   System.Web, Version=2.0.0.0, Culture=neutral,
   PublicKeyToken=b03f5f7f11d50a3a&quot;</span>
   <span class="attr">connectionStringName</span><span class="kwrd">=&quot;LocalSqlServer&quot;</span>
   <span class="attr">enablePasswordRetrieval</span><span class="kwrd">=&quot;false&quot;</span>
   <span class="attr">enablePasswordReset</span><span class="kwrd">=&quot;true&quot;</span>
   <span class="attr">requiresQuestionAndAnswer</span><span class="kwrd">=&quot;true&quot;</span>
   <span class="attr">applicationName</span><span class="kwrd">=&quot;/&quot;</span>
   <span class="attr">requiresUniqueEmail</span><span class="kwrd">=&quot;false&quot;</span>
   <span class="attr">minRequiredPasswordLength</span><span class="kwrd">=&quot;1&quot;</span>
   <span class="attr">minRequiredNonalphanumericCharacters</span><span class="kwrd">=&quot;0&quot;</span>
   <span class="attr">passwordFormat</span><span class="kwrd">=&quot;Hashed&quot;</span>
   <span class="attr">maxInvalidPasswordAttempts</span><span class="kwrd">=&quot;5&quot;</span>
   <span class="attr">passwordAttemptWindow</span><span class="kwrd">=&quot;10&quot;</span>
   <span class="attr">passwordStrengthRegularExpression</span><span class="kwrd">=&quot;&quot;</span>
   <span class="attr">commentTimeout</span><span class="kwrd">=&quot;&quot;</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">providers</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>In addition to the web.config section shown above, the machine.config contains the default connection string to the database associated with Membership. A different connection string can be configured in web.config. To add additional security the connection string can be encoded and the Membership database password can be encrypted. Many articles have been written discussing these tradeoffs. <a href="http://beta.asp.net/QUICKSTARTV20/aspnet/doc/management/mgmtapi.aspx">Microsoft&#8217;s quick start guides</a> give good examples of how to use encryption in your web.config file.</p>
<h3>The Web.Config File / .aspx Page Security</h3>
<p>Each Web page in the Web application can be assigned a security level. This is done by specifying what role is required to access the page. The syntax in the web.config file is very straightforward. For example, the following web.config snippet specifies that the MembershipGrid.aspx Web page will only be accessible by a user whose role is assigned as Administrator.</p>
<p><system  .web><location path="MembershipGrid.aspx"><system  .web><authorization><allow roles="Administrators" /></authorization></system></location></system></p>
<p></p>
<h3>The Web.Config File / Inside .aspx Page Security</h3>
<p>It is often necessary to provide more granular security than what is previously described. That is, it may be necessary to protect a control such as a button or an aspx page. To do this, it is necessary to programmatically change the attribute associated with the control to be affected. For example, if it is necessary to hide a delete button based on the user&#8217;s role, there are two things that need to be done: first, a method called <strong>ShowButtonBasedOnRole</strong> should be added to the codebehind class of the Web page. It should return <strong>true</strong> if the user is permitted in the role requested, and <strong>false</strong> if the user is not included in the role requested.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">bool</span> ShowButtonBasedOnRole(<span class="kwrd">string</span> RoleOfInterest)
{
  <span class="kwrd">return</span> User.IsInRole(RoleOfInterest);
}</pre>
<p></p>
<p>Then, in the actual aspx page the visibility attribute of the button should be set based on the code-behind method <strong>ShowButtonBasedOnRole</strong>. The actual declaration of the button looks like the following.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">asp</span> <span class="attr">:Button</span>
 <span class="attr">ID</span><span class="kwrd">=&quot;Button1&quot;</span> <span class="attr">runat</span><span class="kwrd">=&quot;server&quot;</span> <span class="attr">Text</span><span class="kwrd">=&quot;Button&quot;</span>
 <span class="attr">Visible</span><span class="kwrd">='&lt;%# (bool) ShowDeleteRowBasedOnRole(&quot;administrator&quot;) %&gt;'</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">asp</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>If a button were to be based on any of multiple roles being set, the passed-in parameter could be changed to a string, and all those roles would be checked before returning with an answer of the whether the user is assigned to one of those roles.</p>
<h3>Using the Member/Role Manager aspx Page</h3>
<p>To use the aspx page included within this project (Membership.aspx) there are a few things that need to be done. First, the two data classes from the article project files need to be copied and included in the target project&#8217;s app_code directory. These two files are MembershipDataObject.cs and RoleDataObject.cs. Then, the aspx file Membership.aspx and its codebehind page, Membership.aspx.cs need to be moved to the current project.</p>
<p>It is very important that this page be protected from being accessed by any user who is not assigned the administrator role. Otherwise, any user would be able to modify any other user&#8217;s logon information. To do this, make sure that in the web.config file the Membership.aspx page is protected. Sample lines from a web.config file to accomplish this are as follows.</p>
<p></p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">system</span> .<span class="attr">web</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">location</span> <span class="attr">path</span><span class="kwrd">=&quot;Membership.aspx&quot;</span> <span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">system</span> .<span class="attr">web</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">authorization</span><span class="kwrd">&gt;</span>
      <span class="kwrd">&lt;</span><span class="html">allow</span> <span class="attr">roles</span><span class="kwrd">=&quot;Administrators&quot;</span><span class="kwrd">/&gt;</span>
      <span class="kwrd">&lt;/</span><span class="html">authorization</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">system</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">location</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">system</span><span class="kwrd">&gt;</span></pre>
<p></p>
<p>Now that the page is protected, it will be impossible to access this page without having Administrator assigned as a role to the current logged-in user account.</p>
<p>The best way to get around this is to execute the code below one time, then remove that code from the Web server. It could, for example, be in the pageload event of an ASP.NET Web page. Then, after this page has been called, delete the page from the server. At that point, the Membership Management Page will only be accessible by logging into the account admin with the password.</p>
<p></p>
<pre class="csharpcode">Roles.CreateRole(<span class="str">&quot;Administrator&quot;</span>);
Roles.CreateRole(<span class="str">&quot;User&quot;</span>);
Roles.CreateRole(<span class="str">&quot;Guest&quot;</span>);
Membership.CreateUser(<span class="str">&quot;admin&quot;</span>, <span class="str">&quot;some strong password here&quot;</span>);
Roles.AddUserToRole(<span class="str">&quot;admin&quot;</span>, <span class="str">&quot;Administrator&quot;</span>);</pre>
<p></p>
<h2>Conclusion<a id="aspmemmansec_topic5" name="aspmemmansec_topic5"></a></h2>
<p>When setting up any Web site, it is important to be cognizant of the users who will use it and understand their associated security requirements. If, for example, the Web site is to be used by an internal group in a company with no external access and no sensitive data, simple security may be sufficient. That is, no encryption, loose password constraints, and so on. Authentication can be used as a convenient method for tracking who is entering data. On the other hand, if the Web site is on the internet and handles confidential data, it is important to lockdown the site as much as possible and only allow authenticated users to access the site.</p>
<p>This article provided a brief introduction on what needs to be considered while setting up security for an ASP.NET Web site. It showed how to add a secure page for modifying Membership and Role information for users logging into the Web site. The next article in this two part series assumes that the security aspects of developing a Web site are understood. It will then describe in detail how the Membership Management page works.</p>
<p></a></p>
</p>
</li>
]]></content:encoded>
			<wfw:commentRss>http://peterkellner.net/2006/01/08/microsoft-aspnet-20-memberrole-management-with-iis-part-1-security-and-configuration-overview/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced (User agent is rejected)
Database Caching 31/36 queries in 0.006 seconds using disk: basic
Content Delivery Network via Amazon Web Services: S3: PetersBlogCDN.s3.amazonaws.com

Served from: peterkellner.net @ 2012-05-22 10:36:12 -->
