Welcome to AspAdvice Sign in | Join | Help

.Net Discoveries

An attempt to pass along some answers I have discovered in my .Net coding.
A Better ASP.Net Member/Role Management Page Pt. 7

Prologue

**Author Note – If you are bewildered by a line (perhaps two) that are red and bold, don’t they that they’re errors, they are corrections/additions. Please see the comments, after the article for comments regarding the highlighted line(s).**

In previous posts, we created “A better ASP.Net Member/Role Management Page”. If you want to follow along, you can create the management page yourself by reviewing all the posts for part 1, part 2, part 3, part 4, part 5 and part 6. In this post, I plan on ‘tying up some loose ends,’ by adding some things that I’d like to have in the management page, but that were over and above basic functionality. Most of this is stuff that I thought of adding while I was creating the page originally, but didn’t want to add yet, or that I didn’t have time to research at the time. Now's my chance to do it.

Problem

Time to add some ‘fluffy stuff’ and add some stuff that will make it just that little bit better… (and I found now that I’ve written this post, add some corrections as well…)

Solution

To get started, let's make it easier to customize the look and feel of the user control.

CssClass Properties

The first thing we’ll look at adding will give you a little more flexibility as far as styling your control. Currently it should look pretty decent but, it looks like Microsoft’s theme, and not our site (I don’t know about yours, but ours doesn’t look like Microsoft’s). I’m sure that we’ll change our site again someday, so it doesn’t make sense to hard code the styles and not have the option to change the styles on the fly. Lucky for us it should be reasonably easy to build in this functionality. I won’t cover how to do every one of them, but if we do it right we should be able to cover a bunch in a couple of groups, and the basics of how it can be done should give you a significant start.

Creating our own styles for the page doesn’t mean we have to remove the styling that we’ve done so far. We’ll just give the user the ability to override our styles to fit their needs. I’ve compiled a list of all the places that I would like to give the user the ability to define the CssClass (I think I got them all, I may have missed some…). We’ll start with the easy ones and show how it’s done and then let you loose on the others. First off, we’ve got three groups of classes that we can set the whole group all at once, our TextBoxWaterMarkExtenders watermark class, our ModalPopupExtender’s background class (the cover for the existing page) and our Panels that will be our modal dialogs (the actual panels being modally displayed). Each of these groups can each be set at once since they’ll be the same (all the watermarks will be the same for instance). Let’s start with our TextBoxWaterMarkExtenders. Here’s the list of controls I compiled:

tweSearchUsersFor
tweSearchUsersForRoles
tweSecurityAnswer (note, this may be misspelled in other posts as tbeSec…)
tweNewUsername (note, this may be misspelled in other posts as tbeNew…)
tweNewRoleName

What we’ll do is create a property for the WaterMarkTextCssClass and then set all their WaterMarkCssClasses when the property is set. Add the following to your back-end code:

Private _TextBoxWatermarkCssClass As String
Public Property TextBoxWatermarkCssClass() As String
    Get
        Return _TextBoxWatermarkCssClass
    End Get
    Set(ByVal value As String) 
        _TextBoxWatermarkCssClass = value
        tweSearchUsersFor.WatermarkCssClass = value
        tweSearchUsersForRoles.WatermarkCssClass = value
        tweSecurityAnswer.WatermarkCssClass = value
        tweNewUsername.WatermarkCssClass = value
        tweNewRoleName.WatermarkCssClass = value
    End Set
End Property

I cheated, I use the Refactor! tool, that I’ve mentioned before, so all I had to do to create the property is write the declaration line and then right click on it and select and refactor. I then added all the TextBoxWaterMarkExtender controls from the list to the set portion of the property and assigned the value passed in to their WatermarkCssClass property. Now go to our test page that tests our user control and in the HTML markup that uses the control, add an attribute for WatermarkCssClass and assign it a css class with different style than the one we’re using (my css class had one line: color: red;). Run it and you’ll see that it overrides the one that we assigned in the control’s front end markup. (Note, I’ve found that when you add properties this way, you may need to close and reopen the page that’s using the control otherwise it may not show our new property as an intellisense available attribute).

One other small note: if you notice I saved the property to a global variable. Realistically, we could just put the value to the controls and then call it good, but if we want to pull it and look at later, it then it might be nice to pull it from a central point rather than from one of the controls.

Next, we’ll do the ModalPopupExtender BackgroundCssClass. The ModalPopupExtenders that I cataloged are:

mpeCreateUser
mpeMessageDialog
mpeDeleteUserConfirm
mpeEditUser
mpeChangePassword
mpeConfirmResetPassword
mpeChangeSecurityQuestion
mpeChangeUsername
mpeDeleteRoleConfirm
mpeChangeRoleName
mpeRoleRenameConfirm

To create their property, add the following to your back-end code:

Private _ModalPopupBackgroundCssClass As String
Public Property ModalPopupBackgroundCssClass() As String
    Get
        Return _ModalPopupBackgroundCssClass
    End Get
    Set(ByVal value As String)
        _ModalPopupBackgroundCssClass = value
        mpeCreateUser.BackgroundCssClass = value
        mpeMessageDialog.BackgroundCssClass = value
        mpeDeleteUserConfirm.BackgroundCssClass = value
        mpeEditUser.BackgroundCssClass = value
        mpeChangePassword.BackgroundCssClass = value
        mpeConfirmResetPassword.BackgroundCssClass = value
        mpeChangeSecurityQuestion.BackgroundCssClass = value
        mpeChangeUsername.BackgroundCssClass = value
        mpeDeleteRoleConfirm.BackgroundCssClass = value
        mpeChangeRoleName.BackgroundCssClass = value
        mpeRoleRenameConfirm.BackgroundCssClass = value
    End Set
End Property

Nothing much different than we did before, just more controls to assign to. Again, add an attribute to your control declaration on the test page and see the difference if you run it (my popup background is orange now :-0 ). Finally for the easy ones, let’s do the panels that will be displayed as the ModalPopup. The list I compiled are:

pnlMessageDialog
pnlDeleteUserConfirm
pnlCreateUser
pnlEditUser
pnlChangePassword
pnlConfirmResetPassword
pnlChangeSecurityQA
pnlChangeUsername
pnlDeleteRoleConfirmation
pnlChangeRoleName
pnlChangeRoleNameConfirm

And one more time add the property and assign the values. Add the following to the backend code:

Private _ModalPopupCssClass As String
Public Property ModalPopupCssClass() As String
    Get
        Return _ModalPopupCssClass
    End Get
    Set(ByVal value As String)
        _ModalPopupCssClass = value
        pnlMessageDialog.CssClass = value
        pnlDeleteUserConfirm.CssClass = value
        pnlCreateUser.CssClass = value
        pnlEditUser.CssClass = value
        pnlChangePassword.CssClass = value
        pnlConfirmResetPassword.CssClass = value
        pnlChangeSecurityQA.CssClass = value
        pnlChangeUsername.CssClass = value
        pnlDeleteRoleConfirmation.CssClass = value
        pnlChangeRoleName.CssClass = value
        pnlChangeRoleNameConfirm.CssClass = value
    End Set
End Property

Check it if you want, my control is staring to look pretty odious (I’m choosing some truly awful colors, just for kicks).

For the remaining CssClasses, we have a number of other one-off’s that we’ll need to address individually. I won’t be addressing them in this post, but I’ll list them and then you can add the property code to assign their classes just as we did above. The controls I cataloged were:

tblSearchUsers
tblSearchUsersHeader
tblSearchUsersBody
gvManageUsers – CssClass, RowStyleCssClass, AlternativeRowStyleCssClass
tblCreateUser
tblCreateRole
tblCreateRoleHeader
gvRoles – CssClass, RowStyleCssClass, AlternativeRowStyleCssClass
tblSearchForUsersRole
tblSearchForUsersRoleBody
gvUsersForRole – CssClass, RowStyleCssClass, AlternativeRowStyleCssClass

Two notes: 1. Some of these can likely be combined (such as the GridView’s CssClasses) since I want them to look the same I’ll set them the same time, 2. If you go back trough your code, you’ll notice that the tables and the Header and Body elements here listed (i.e. tblSearchUsers and tblSearchUsersHeader), may need to have an ID attached to them so we can call them in the back-end code (they may not already have ID’s). This means that you’ll be adding an ID to a table (tblSearchUsers) and to a TableCell (tblSearchUsersHeader – as it isn’t truly a header, it’s a TableCell masquerading as one) in your front-end code so you can call it directly in the back-end. Then we’ll create a property that calls it a header (i.e. headerCssClass) – so even some child elements will have ID’s assigned. Create and assign the properties as you did above.

Realistically, any CSS that we created in the front-end, you can setup as a property and override as you desire.

Real-time Username Notification

One of the things I thought would be really great to have from the get go was to add real-time username availability notification. What I mean by that is for those locations where the admin creates or changes the username, allow the dialog to inform the admin whether the username is available AS they are typing. Something akin to this (and the actual demo here).

When I started this project, the authors weren’t fully finished with develpment, but they did finish by the time I finished our control. Unfortunately (in our instance), they created a user control. BUT, wanting to put my control together as a self-contained usercontrol, I didn’t want to add another external control to the mix. I looked into reusing the code and integrating it into my control, and it could be done. What I didn’t think about though is that the front-end page needs to call to something, via Javascript/AJAX as you are typing. Any way it is sliced, (at least from what I found on the site) this requires a web service of some kind on the back-end (that’s the something). Even if I can call a function contained in the same page (which the control alas is NOT, it’s a control not a page), it has to be declared as a web service so that it can be called by the AJAX (there’s an interesting article on using jQuery to call a page method that I read).

To get it to work, the jQuery has to call a page, by name, and then the method (we could pass the page name to the control by property in the front-end and write it into our javascript code so the jQuery can call it (I’ve written on injecting into javascript before). We also would have to enable the page to support web services, which I gather necessitates some changes to the web.config. This then means that we’re not self contained. We have already broken our self contained requirement by adding functionality for changing the username (and will again in the next section), but realistically, to get this functioning, wasn’t worth the time I thought I’d end up putting in. The admin will get notification that the username is not available, it just won’t be while typing.

Role Descriptions

Here’s another interesting bit of functionality that Microsoft left out (and I can’t discern why). Let’s say we want to put in a description of the role so that the admin can go back and remember what each role is meant for (the roles I’m using are descriptive to departments here at the company, but not necessarily to what rights the user gets). Descriptions would be handy. What to do? Well if you examine the roles table in the database, you’ll see that Microsoft conveniently added a description field to the database (nvarchar 256). So it seems that we’d be able to pretty easily enter a description. NOPE. Apparently, this is unimplemented functionality. There is nothing in the role provider to facilitate this. If we want to do it, we’ll have to again break our self-contained directive, and add some database functionality. We can create a property that we’ll use to specify whether the external functionality has been created like we did with our Change Username functionality. But, alas it means breaking the self-contained directive AGAIN.

I’m going break our directive anyway, I believe it will have enough use for me that I’ll go ahead and break our rules again. First we need to start with modifying the front-end code. We want to add another column to our Manage Roles GridView. Add the following to the definition of gvRoles. Add it between the RoleName and 'Assign Users’ columns (as the 2nd column):

<asp:TemplateField HeaderText="Description" Visible="false">
    <HeaderStyle HorizontalAlign="Left" />
    <ItemTemplate>
       <asp:label runat="server" ID="lblRoleDescription" 
        Text="<%# GetRoleDescription(Container.DataItem.ToString()) %>" />
        (<asp:LinkButton runat="server" ID="lnkRoleDescription"
              ForeColor="Black" Text='Edit'
              CommandName="EditRoleDescription"
              CommandArgument='<%# Container.DataItem.ToString() %>' 
              OnCommand="RoleLinkButtonClick"/>)
    </ItemTemplate>
</asp:TemplateField>

You’ll notice that we setup another column for the description, it is composed of 2 parts, a label for the description, and an edit link (you may notice that the control for that is surrounded by parentheses, that’s not a typo, they’re string literals for the HTML). You’ll also notice that we call a function GetRoleDescription. We’ll have to define that in our back-end code later. We also set the column’s visible property false so by default it is NOT shown. I put two controls in our column, one that displays the description name, and one that displays an edit link.

Originally, I thought to put the description functionality with the change role name functionality, however I rethought that, as the change role name is already a special circumstance. We’ll keep them separate which means we’ll add another dialog for changing the description. As for adding a description when the admin creates a role, since the description functionality is not out of the box, I’ll force the admin to create a new role and then take a second step to enter a description.

We’ll want to create a new modal dialog for editing our role description. Add the following to the bottom of our front-end code:

    <%-- Change Role description Dialog --%>
<asp:UpdatePanel id="upnlRoleDescription" runat="server"
   ChildrenAsTriggers="true">
    <ContentTemplate>
        <asp:Panel ID="pnlRoleDescription" runat="server"
             style="display: none;" CssClass="modalPopup"
             HorizontalAlign="Center">
            Enter a description for the '<asp:label id="lblRoleDescriptionName"
                runat="server" Text="" />' role.<br /><br />
            <asp:Table ID="Table1" runat="server">
                <asp:TableRow>
                    <asp:TableCell HorizontalAlign="Right">
                        Role description:
                     </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Left">
                        <asp:TextBox ID="txtRoleDescription" runat="server" />
                        <cc1:TextBoxWatermarkExtender ID="tweRoleDescription"
                              TargetControlID="txtRoleDescription"
                              WatermarkText="Enter role description."
                              WatermarkCssClass="watermarked" runat="server" />
                    </asp:TableCell>
                </asp:TableRow>
            </asp:Table>
            <br />
            <asp:LinkButton ID="lnkRoleDescriptionSave"
                CausesValidation="true" runat="server" Text="Save" />&nbsp;
            <asp:LinkButton ID="lnkRoleDescriptionCancel" runat="server"
                 Text="Cancel" />
        </asp:Panel>
        <asp:Button ID="btnFakeMPERoleDescription" runat="server"
              style="display: none;" />
        <cc1:ModalPopupExtender id="mpeRoleDescription" runat="server"
            TargetControlID="btnFakeMPERoleDescription"
            PopupControlID="pnlRoleDescription"
            BackgroundCssClass="modalBackground" />
    </ContentTemplate>
</asp:UpdatePanel>

It’s pretty standard for our dialogs. We have one TextBox, for the description and two LinkButtons for save and cancel. In keeping with previous dialogs, let’s display this using our SetUI subroutine. Add the following to our SetUI enumeration:

EnableRoleDescription
RoleDescriptionDialog

Then we’ll add some functionality to our SetUI subroutine. Add the following two cases to your SetUI case statement:

Case SetUIModes.EnableRoleDescription
    gvRoles.Columns(1).Visible = True
Case SetUIModes.RoleDescriptionDialog
    mpeRoleDescription.Show()

This just takes care of displaying things. The first case will make our column visible if the property is set to true. The second shows the dialog. We’ll also need to add some functionality to our RoleLinkButtonClick event handler. Add the following If statement to your RoleLinkiButtonClick:

If e.CommandName.Equals("EditRoleDescription") Then
    lblRoleDescriptionName.Text = CStr(e.CommandArgument)
    txtRoleDescription.Text = GetRoleDescription(e.CommandArgument)
    SetUI(SetUIModes.RoleDescriptionDialog)
End If

This will set the textbox to the current role description and then show the edit dialog when the admin clicks the ‘Edit’ link.

Next, let’s setup the save and cancel buttons in the role description dialog. Add the following to your back-end code to your lnkRoleDescriptionCancel_Click event handler:

txtRoleDescription.Text = String.Empty

This simply clears our TextBox if we cancel so we don’t have any loose ends. Next add the following to our lnkRoleDescriptionSave_Click event handler:

If UpdateRoleDescription(lblRoleDescriptionName.Text, _
        txtRoleDescription.Text) = True Then
    lblMessageDialog.Text = "Role description successfully updated."
    SetUI(SetUIModes.MessageDialog)
    gvRoles.DataSource = Roles.GetAllRoles()
    gvRoles.DataBind()
Else
    lblMessageDialog.Text = "Changing the role's description was _
         unsuccessful."
    SetUI(SetUIModes.MessageDialog)
End If

Here we call a UpdateRoleDescription subroutine and pass it the role’s name and the new description. If it returns successful, we’ll rebind the GridView with new data, and display a success message. If it fails, we’ll display a failure message. In our SQL code, we will be retrieving the role by the role’s name. Since we won’t be allowed by our provider to add a role name more than once per ApplicationID (more on that later), we should be ok doing it this way.

We’ll need to define some SQL before proceeding. We’ll create two stored procedures for our database. First, let’s define the GetRoleDescription’s stored procedure:

CREATE PROCEDURE aspnet_Roles_GetRoleDescription
    @RoleName nvarchar(255),
    @ApplicationName nvarchar(255),
    @RoleDescription nvarchar(255) OUTPUT
AS
DECLARE @ApplicationID nvarchar(255)
SELECT @ApplicationID = ApplicationID FROM aspnet_Applications
   WHERE ApplicationName = @ApplicationName

SELECT @RoleDescription = Description FROM aspnet_Roles
   WHERE RoleName = @RoleName AND ApplicationID = @ApplicationID

First off, we create three SQL variables, two will be input and one output. The input variables will pass in our role name and our application name. We’ll use the application name to pull the ApplicationID and then use the role name and ApplicationID to target the description. We need to include the ApplicationID since we can create two roles with the same name in the database IF they have different applications assigned to them. If we target by role name only, we could be effecting multiple roles, especially when we get to updating the role’s description. Finally we’ll retrieve the description and assign that to our output variable.

Next, we’ll define our UpdateRoleDescription stored procedure as follows:

CREATE PROCEDURE aspnet_Roles_UpdateRoleDescription
    @RoleName nvarchar(255),
    @ApplicationName nvarchar(255),
    @RoleDescription nvarchar(255),
    @Results bit OUTPUT
AS
DECLARE @ApplicationID nvarchar(255)
SELECT @ApplicationID = ApplicationID FROM aspnet_Applications
   WHERE ApplicationName = @ApplicationName

UPDATE aspnet_Roles SET Description = @RoleDescription
   WHERE RoleName = @RoleName AND ApplicationID = @ApplicationID

SET @Results = @@ROWCOUNT

This time we’re creating three input variables, since we need to pass in the new description as well as the role name and application name. Much like the previous stored procedure, we’ll use the application name to retrieve the ApplicationID and then use that to target the correct role. Then we update the description for the role and return the affected row count as a result. This way, we can check the success of our operation. We should only get a 1 back (meaning one row affected). If we get anything else, we’ll have failed.

Now we’re ready to do some hookups in the back-end code. First, we’ll define our GetRoleDescription function. Add the following function to your back-end code:

Public Function GetRoleDescription(ByVal sRoleName As String, _
       Optional ByVal iOrdinalForConnectionString As Integer = 0) As String  

  If _RoleDescriptionFunctionality = _
           RoleDescriptionSettings.DbIsSetup Then

    Using cn As New SqlConnection(ConfigurationManager.ConnectionStrings
      (iOrdinalForConnectionString).ConnectionString)
        Dim cmd As New SqlCommand("aspnet_Roles_GetRoleDescription", cn)
        cmd.CommandType = Data.CommandType.StoredProcedure
        cmd.Parameters.Add("@RoleName", _
              Data.SqlDbType.NVarChar).Value = sRoleName
        cmd.Parameters.Add("@ApplicationName", _
              Data.SqlDbType.NVarChar).Value = Roles.ApplicationName
        cmd.Parameters.Add("@RoleDescription", Data.SqlDbType.NVarChar, _
              255).Direction = Data.ParameterDirection.Output
        cn.Open()
        Try
            cn.Open()
            cmd.ExecuteScalar()
        Catch ex As Exception
            Return string.empty
        Finally
            cn.Close()
        End Try
        If cmd.Parameters("@RoleDescription").Value.Equals _
                  (System.DBNull.Value) Then
            Return String.Empty
        Else
            Return cmd.Parameters("@RoleDescription").Value
        End If
    End Using
  Else
    Return String.Empty
  End If

End Function

In the parameter list for our function, you’ll notice we pass in our role name, and we also pass in an optional parameter for our connectionstring. If you remember back to part 5 in the series, we added some database functionality for changing the username. I mentioned when we created the back-end code for ChangeUsername, that this was perhaps the least flexible part of our entire project, since we can’t automatically pull the current connectionstring from anywhere. We need to have a way to retrieve it so we can create a connection to our database though. Since the connectionstrings are in an array, we can specify them by ordinal number. In my simple application here at work, my connectionstring is 0 (the only one). To target another connectionstring for our connection, we would need to determine the ordinal number of the connectionstring and pass it in. (UGLY I agree… excuse me while I hurl…). We may be able to set this via property as we did above with cssClasses so that we don’t have to modify the code to change the connectionstring.

The function creates a connection, and then a command object. We load the command object up with our parameters. Nothing fancy, except one item of note, we specify a size for the return parameter. If we don’t specify the size, our application will return an error about not allowing a string of size 0. We’ll then open the connection and try to execute. We’ll use a try catch and if we get an error, we’ll return an empty string. If we’re successful, we’ll check to see if we got a null value returned. If so, we’ll again return an empty string. If it’s NOT null, we’ll return the description.

Next, let’s define our UpdateRoleDescription function:

Public Function UpdateRoleDescription(ByVal sRoleName As String, _
      ByVal sNewDescription As String, _
      Optional ByVal iOrdinalForConnectionString As Integer = 0) As Boolean

Using cn As New SqlConnection(ConfigurationManager.ConnectionStrings _
       (iOrdinalForConnectionString).ConnectionString) 
    Dim cmd As New SqlCommand("aspnet_Roles_UpdateRoleDescription", cn)
    cmd.CommandType = Data.CommandType.StoredProcedure
    cmd.Parameters.Add("@RoleName",_ 
       Data.SqlDbType.NVarChar).Value = sRoleName
    cmd.Parameters.Add("@ApplicationName", _
       Data.SqlDbType.NVarChar).Value = Roles.ApplicationName
    cmd.Parameters.Add("@RoleDescription", _
       Data.SqlDbType.NVarChar, 255).Value = sNewDescription
    cmd.Parameters.Add("@Results", _
       Data.SqlDbType.Bit).Direction = Data.ParameterDirection.Output
    cn.Open()
    Try
        cmd.ExecuteNonQuery()
    Catch ex As Exception
        Return False
    Finally
        cn.Close()
    End Try
    Return cmd.Parameters("@Results").Value
End Using
End Function

Here we’re passing in three parameters, our role name, our new description name, and again our odious connectionstring ordinal. We create a connection and a command, load it up with our data, and then execute the query. If it fails, we return false, if it runs, we’ll return the result (if it fails, it’ll be false that gets returned).

Viola, now we can add role descriptions. Why Microsoft hasn’t bothered to make this part of the Roles provider I’ll never know. I mean why build it into the database if you aren’t going to use it? Anyhow, Role descriptions at our disposal.

Fixing Change Username Functions

In the process of adding role description functionality, I found that I didn’t properly execute our ChangeUsername function. If you remember, in the above section, we passed in the applicationName so that we target only the Role that we want to. Technically, we can have more than one username or more than one role in a table if we add it using a different applicationName. I didn’t take that into account when I put together ChangeUsername. I neglected to use the application name SO, technically the code would change ALL the usernames rather than just the one we want. Let’s make some changes so that it behaves properly. Let’s modify our ChangeUsername function to include an applicationName parameter. Add the following just below our @newUsername parameter in our ChangeUsername function:

cmd.Parameters.Add("@applicationName", _
   Data.SqlDbType.NVarChar).Value = Membership.ApplicationName

And then we’ll need to modify our aspnet_Membership_ChangeUsername stored procedure. The SQL to update the stored procedure is as follows (changes are in bold):

ALTER PROCEDURE aspnet_Membership_ChangeUsername
    @currentUsername nvarchar(255),
    @newUsername nvarchar(255),
    @applicationName nvarchar(255),
    @results bit OUTPUT
AS

DECLARE @ApplicationID nvarchar(255)
SELECT @ApplicationID = ApplicationID FROM aspnet_Applications
   WHERE ApplicationName = @ApplicationName
 

    UPDATE aspnet_Users
    SET UserName = @newUsername,
        LoweredUserName = LOWER(@newUsername)
    WHERE LOWER(UserName) = LOWER(@currentUsername)
        AND ApplicationID = @ApplicationID

    set @results = @@ROWCOUNT

There, now we properly target our specific username.

One other thing I want to update is to reset the change username dialog when the admin clicks cancel. To do this, all we need to do is add two lines to our lnkChangeUsername_Click event handler. Add these lines right after the End If line, and before the lblCurrentUsername.text line:

txtNewUsername.Text = String.Empty
divUserAvailablity.InnerText = String.Empty

Previously, if we canceled changing the username, the the new username textbox and an error message, if applicable, would be there when we reopened it. Now it won’t, it will be pristine like it’s supposed to be.

Epilogue

And there it is, “A Better Asp.Net Member/Role Management Page”. There were a couple other tings I thought about adding to the mix, like rewriting all the confirmation dialogs so that there is one common dialog that we could reuse everywhere we confirmed things, but I didn’t really want to go through the trouble of rewriting the whole mess just to reduce the code, it wasn’t worth it.

If anyone has something that they added, that they’d like to tell us about, drop me a line and I’ll put it in the comments section. I’m sure we’d all love to see it.

But for me, that’s it for the management page. I’ll be putting it into production now that I’m done writing it (yes, I was still finishing it), and unless there are any issues that people point out or errors that need corrected. I’m calling it good and being done! PHEW!

Posted: Monday, March 30, 2009 4:13 PM by Yougotiger

Comments

Yougotiger said:

** Author Comment** - Heaven forbid, I thought I wasn't going to get away without correcting at least one of the posts. But I guess not.

In my testing with using my wonderful control in another setting, I found something wrong. I guess I assumed that if a column was set to visible = false, it would just not exist. However if we run our application, even with our RoleDescriptionFunctionality set to DbIsNotSetup which hides our roleDescription column, it doesn't preclude our GetRoleDescription function from being called. This means that if our DB isn't setup, we may have some issues regardless. So To fix this I added an If Then statment to the function, so that if RoleFunctionality isn't enabled, it skips the the database portion and returns string.empty. You can find the changed portion in bold red.

Also, I found that the part it was crashing on was the cn.Open statment. And becuase it was outside the try catch statement, it was an unhandled exception. So I moved it into the Try Catch statement so that it would be handled were there to be a problem.

# April 3, 2009 12:41 AM

tony said:

Hi there I've been following your blogs for quite a while. I'd say this is the best documents regarding the member/role management. are there a source downloadable regarding all the steps you've been guide through?
# June 19, 2009 3:55 AM

Yougotiger said:

** Author Comment**

In answer to Tony's question, unfortunately aspadvice doesn't allow me to post any files. I don't really have a dedicated place to put the files in the mean time so... I thought about posting a the full code, but that makes for an aweful long post. Does any one have any comments either way?

# June 19, 2009 12:35 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the code you see below

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS