Advanced ASP.NET Development

luni, 10 mai 2010

Unit Testing With the ASP.NET Membership Provider – the Memory Membership Provider

Since it was first launched, along with the ASP.NET 2.0, the Provider Model proved its usefulness and reliability and has been widely used by various web applications, in different scenarios.

A good development practice is to have “test driven development”, or at least to write reliable unit tests for the “business logic” code and, since the web security (membership and roles) is an important part of the application’s “business logic” layer, the logical conclusion is that the Membership, Roles and Profile providers should be easily handled by unit tests and mocking frameworks (such as moq). But this is not possible, since most of the mocking frameworks require virtual methods or interfaces and the Membership Provider’s base (abstract) class doesn’t have any virtual methods. Creating wrappers for Membership provider is not the best way to go, since this adds more unwished code complexity.

Some business logic components may use the Membership Provider in this way:

public partial class
UserImport
{

public
MembershipProvider Members {get; set;}

public void
ImportUser(SomeUserData userData)
{
………
MembershipUser user = this.Members.CreateUser(username, password, email, question, answer, isApproved, providerUserKey, out status);
……..
}
}

Creating, running and maintaining a unit test for the ImportUser method implies using the ASPNETDB database, thus leading to poor testing performance.

Having this, I think the best option is to have a custom Memory Membership Provider, that may be used only for Unit Testing purposes, to easily manage users in memory without using the ASPNETDB database.

As already said, the primary objective of this Membership Provider is to easily handle the Users in memory, as properly handle the unit testing of other dependant “business logic” components.

public class
MemoryMembershipProvider : MembershipProvider
{
    public MemoryMembershipProvider()
    {
        this.Users = new List<MembershipUser>();
    }

The “Users” list is the memory data store.

Below are some possible implementations of common membership Provider methods:

public override
MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
    status = MembershipCreateStatus.Success;
    var theResult = default(MembershipUser);
    var searchForDuplicateUsername = from p in this.Users
                                     where p.UserName.ToLowerInvariant() == username.ToLowerInvariant()
                                     select p;
    if(searchForDuplicateUsername.Count() != 0)
    {
        status = MembershipCreateStatus.DuplicateUserName;
    }
    if(status == MembershipCreateStatus.Success)
    {
        theResult = new MembershipUser("MemoryProvider", username, Guid.NewGuid(), email, passwordQuestion, null, isApproved, false, DateTime.Now, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue);
    }
    return theResult;
}

public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
    totalRecords = this.Users.Count;
    var theResult = new MembershipUserCollection();
    var startRowIndex = pageSize * pageIndex;
    foreach (var user in this.Users.Skip(pageSize * pageIndex).Take(pageSize))
    {
        theResult.Add(user);
    }

    return theResult;
}

public override
MembershipUser GetUser(string username, bool userIsOnline)
{
    var query = from p in this.Users
                where p.UserName.ToLowerInvariant() == username.ToLowerInvariant()
                select p;

    returnquery.SingleOrDefault();
}

public overrideMembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
    var query = from p in this.Users
                where p.ProviderUserKey == providerUserKey
                select p;

    returnquery.SingleOrDefault();
}

}

Of course, also the other methods of the Membership Provider may be custom implemented, as to properly support the unit testing and the various “business logic” scenarios.

Happy coding testing !

vineri, 8 ianuarie 2010

jQuery Validation – Creating ASP.NET Validation Groups with jQuery “not” and “ignore”.

Since jQuery offers great means to perform data validation in ASP.NET, there are still a couple of ASP.NET features that jQuery doesn’t know to handle by default: for which we just need to add some simple tweaks.

As we already seen that the issues of jQuery Validation –and jQuery generally- with the ASP.NET Ajax UpdatePanel have an workaround here, there’s still the very useful functionality of ASP.NET Validation Groups. Since ASP.NET allows only on HTML FORM element in page, the Validation Groups have been created to logically group distinct ASP.NET Validators. For the common jQuery Validation library this feature may seem useless, since generally HTML pages allow multiple FORM elements: each of the parameter input logical form consists of a distinct HTML FORM. Therefore, we need a way of emulating ASP.NET Validation Groups with jQuery, having a single HTML FORM.

Let’s consider the following ASP.NET mark-up that contains two logical parameter input forms: “#info” and “#address”:

<div id="info">
        <
label>Username</label>
        <
asp:TextBox ID="UsernameTextBox" runat="server" CssClass="required"></asp:TextBox>
        <
br />
        <
label>Email</label>
        <
asp:TextBox ID="EmailTextBox" runat="server" CssClass="required email"></asp:TextBox>
        <
br />
        <
label>Name</label>
        <
asp:TextBox ID="NameTextbox" runat="server"></asp:TextBox><br />
        <
asp:Button ID="SubmitButton" runat="server" OnClick="SubmitButton_Click" Text="Submit info" CssClass="submitInfo" />
</
div>

<
div id="address">
        <
label>Address</label>
        <
asp:TextBox ID="AddressTextBox" runat="server" CssClass="required"></asp:TextBox><br />
        <
asp:Button ID="SubmitAddressButton" runat="server" OnClick="SubmitButton_Click" Text="Submit address" CssClass="submitAddress" />
</
div>

This would be the regular jQuery form validation setup:

$(document).ready(function() {

    //registering the common jQuery FORM Validation
   
formValidation = $("form").validate({
        submitHandler: function(form) {
            form.submit();
        }
    });

We’re going further to consider these two (#info and #address) as our distinct validation groups. The main idea of separating validation groups is to inform jQuery Validation that it should just ignore any input elements outside the active group. For this, we’re going to use the jQuery validate() ignore option and the jQuery not selector, by “telling” dynamically the validation object to ignore all the input elements outside the active logical form.

In ASP.NET, the ValidationGroup property had to be setup on each of the ASP.NET Validator controls and again on the Button that triggered the postback. Using this approach we just need to setup the postback buttons with the proper validation group, by handling the Button click event where to setup the validation right ignore option. jQuery not selector is used to differentiate between DOM elements.

//Similar to ASP.NET, setup of the Button right ValidationGroup "info",
//by ignoring any input element that is not in the #info div.
$(".submitInfo").click(function(item) {
    formValidation.settings.ignore = "div:not(#info) > *";
});

//Similar to ASP.NET, setup of the Button right ValidationGroup "address",
//by ignoring any input element that is not in the #address div.
$(".submitAddress").click(function(item) {
    formValidation.settings.ignore = "div:not(#address) > *";
});

//…ending the $(document).ready()

…});

That’s it!

marți, 5 ianuarie 2010

Using LINQ to XML to create an ASP.NET XML Roles Provider

Since Authorization and Authentication are important aspects of websites, ASP.NET provides good support for these: ASP.NET 2.0 introduced the Membership and Roles provider model, and offers some really useful built-in providers: SQL Membership Provider, SQL Roles Provider, Windows Token Roles Provider, etc.

However, not every website is that complex to make use of these heavy components: take for instance the proof of concepts.
For the SQL providers we need to setup a database (option that may not be always available), to create pages for users and roles management, that also require some time to be developed. The Windows/Active Directory providers would only work for enterprise applications that usually require some intranet infrastructure.
Therefore, sometimes we need a more simple solution to store users and roles, like a XML file, but also make use of the great Membership and Roles provider model.

The benefits of a XML Roles Provider are quite simple: simple to implement it, to manage roles and user-roles, to deploy and configure. It is very simple to manage roles and user-roles: just manually edit the XML file. As already mentioned before, this is only suited for simple websites, where there is a limited set of users. The XML Roles Provider would work with Windows Authentication, but also with Forms Authentication and a custom XML Membership Provider.

To implement the XML Roles Provider, just create a new Roles Provider, by inheriting from the System.Web.Security.RoleProvider abstract class and override the abstract methods. For minimum authorization functionality, just add some actual implementation to these basic methods: public override string[] GetRolesForUser(string username) and public override bool IsUserInRole(string username, string roleName).

The XML Roles Provider uses .NET 3.5 LINQ To XML for querying data from an XML file located in the “/App_Data” folder. The XML file is not accessible via HTTP to users, since IIS restricts access to this ASP.NET folder. Since we would want the XML Roles Provider to get updated when the XML file is edited, one option is to use the FileSystemWatcher to monitor the changes occurred on the XML file.

XML file structure used by the XML Roles Provider

<?xml version="1.0" encoding="utf-8" ?>
<
roles>
  <
role roleName="Administrator">
    <
user>Admin</user>
    <
user>Mike</user>
  </role>
  <
role roleName="Manager">
    <user>Lucy</user>
  </role>
  <
role roleName="Customer">
    <user>Alex</user>
    <user>George</user>
    <user>Jan</user>
    <user>Mary</user>
  </role>
</
roles>

The XML Roles Provider Implementation

public class XmlRoleProvider : RoleProvider
{
    public override void AddUsersToRoles(string[] usernames, string[] roleNames)
    {
        throw new NotImplementedException();
    }

    public override string ApplicationName
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    public override voidCreateRole(string roleName)
    {
        throw new NotImplementedException();
    }

    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
    {
        throw new NotImplementedException();
    }

    public override string[] FindUsersInRole(stringroleName, stringusernameToMatch)
    {
        throw new NotImplementedException();
    }

    public override string[] GetAllRoles()
    {
        throw new NotImplementedException();
    }

    public override string[] GetRolesForUser(string username)
    {
        var theResult = from p inDocument.Root.Elements("role").Elements("user")
                        where p.Value == username
                        select p.Parent.Attribute("roleName").Value;

        return theResult.ToArray();
    }

    public override string[] GetUsersInRole(string roleName)
    {
        throw new NotImplementedException();
    }

    public override bool IsUserInRole(string username, string roleName)
    {
        var userRoles = this.GetRolesForUser(username);
        var theResult = userRoles.Contains(roleName);
        return theResult;
    }

    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
    {
        throw new NotImplementedException();
    }

    public override bool RoleExists(string roleName)
    {
        throw new NotImplementedException();
    }

    private FileSystemWatcher _watcher;
    private XDocument _document;
    private object _docLock = new object();

    public XDocument Document
    {
        get
       
{
            if (this._document == null)
            {
                string path = HttpContext.Current.Server.MapPath("~/App_Data/roles.xml");

                //Perform some locking:
               
lock (this._docLock)
                {
                    if (this._document == null)
                    {
                        this._document = XDocument.Load(path);
                    }
                }

                if (this._watcher == null)
                {
                    this._watcher = new FileSystemWatcher(HttpContext.Current.Server.MapPath("~/App_Data"), "*.xml");
                    this._watcher.NotifyFilter = NotifyFilters.LastWrite;
                    this._watcher.Changed += new FileSystemEventHandler(watcher_Changed);
                    this._watcher.EnableRaisingEvents = true;
                }
            }

            return this._document;
        }
    }

    void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        lock (this._docLock)
        {
            this._document = null;
        }
    }
}

marți, 15 decembrie 2009

jQuery Validation and ASP.NET UpdatePanel

Data Input Validation

It’s no secret that data validation is a very important aspect of software application development, regardless of the technology or the application nature itself. Either we're talking about a server, a system service, a desktop or web application, developed in C/C++, C#, ASP.NET, PHP...etc, data validation is a must: we just can't deliver any real applications to the end-users, without having at least a basic level of data validation.

As you've probably guessed from the title of this topic, this post is going to refer strictly to the data input validation for ASP.NET websites.

Since validation is such a very complex and important topic, I find it quite normal to be so may approaches and discussions out there: which one is the best?

I'm quite a fan of the ASP.NET Web Forms, including the ASP.NET integrated validation framework; but considering the exiting trends in client (JavaScript) development, I must admit that the existing ASP.NET RAD (Rapid Application Development) isn't much more of a RAD anymore, since jQuery has already created new standards and added new reference to simplicity and having fun while coding.

Probably most of you have already written some code with jQuery and know what I'm talking about: jQuery is really simple and fun to use; when to use it? whenever you need to write some JavaScript.

ASP.NET Validation Controls

Now let's get back to the ASP.NET validation: since of it's early ages (yes, ASP.NET is starting to have an age :) ), the Web Forms included some smart and quite useful validation controls, there were some for usual scenarios:

  • checking for required fields,
  • checking for passwords and retype passwords match,
  • checking for regular expressions (emails, URLs, phones...etc),
  • checking for data type format.

      but also custom scenarios were possible to follow, due to custom validation features.

    In most cases, this validation is performed on client side, using JavaScript, but some of the validation happens only on server-side, once with the post-back (C# code).

    Having ASP.NET validations in a Web Form is was very easy: just for every single data input control add such a validation control:

    <asp:TextBox ID="EmailTextBox" runat="server" CssClass="required"></asp:TextBox>
       <asp:RequiredFieldValidator ID="EmailRequired" runat="server" ControlToValidate="EmailTextBox"></asp:RequiredFieldValidator>

    This is indeed quite simple, efficient and straightforward, but think that for a couple of fields you may need to perform multiple checks. An "email" field is required, but also we need to check if the input value is really in an email format, meaning it does contain the "@" character, a domain name and domain extension, and all the email parts contain only valid characters. This means, that for the example above we also should add a Regular Epression Validator, to check the field format:

    <asp:RegularExpressionValidator ID="EmailRegEx" runat="server" ControlToValidate="EmailTextBox" ValidationExpression="..."></asp:RegularExpressionValidator>

    Now, just imagine creating such a data input form that has 20 fields (yes, they do exist), or worse (better?), imagine that your website has lots of such data input forms: this means that most of the actual ASP.NET code would mean adding the right validation to the input fields, over and over again.

    All these mean lots of code to write, less productivity and more time spent to create very simple features, not to mention the code duplication, which is involved by the ASP.NET Validation controls themselves and also the huge amount of bloating code that stands between developers and designers.

    Wouldn’t be more simple to just register the set of fields for a certain validation type (required field, regular expression check..etc)?

    Well, there is. jQuery comes to rescue us all, and it does a pretty god job too.

    Validation With jQuery

    Though jQuery great and has a lot of cool features, it doesn’t have validation features built-in. That’s why, these guys have did it: a very cool jQuery validation plug-in.

    The plug-in is using internally CSS selectors, therefore to mark an input field for validation, just set it with the right validation CSS classes.

    <asp:TextBox ID="EmailTextBox" runat="server" CssClass="required email"></asp:TextBox>

    Amazing! this is all the data entry form code to setup validation for form fields.

    Everything works like a charm …until using the ASP.NET Ajax and the mighty UpdatePanel.

    Very unique in this world, the UpdatePanel became the best friend of every ASP.NET developer. It injects with outstanding simplicity AJAX behaviour in any ASP.NET page or user control. But it seems that because of the partial postback many jQuery features just don’t work with the UpdatePanel. The page itself stays the same and only parts from the page are refreshed.

    What to do then? Should we just give up using UpdatePanel or the jQuery validation plug-in?

    Because Web Forms development just cannot replace easily the UpdatePanel for the moment, we should use them both. Yes, with a couple of tweaks, that’s possible.

    Override the ASP.NET Ajax Async Postback Init

    The jQuery validation knows to prevent a regular FORM submit the server, but since the UpdatePanel performs an async. postback –not a FORM submit/postback- , the jQuery validation doesn’t know to prevent this async postback.

    Therefore, we’re going to intercept the ASP.NET Ajax async postback initialization and check whether the form is valid or not.

    //adding a postback request init handler
    Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckValidationStatus);

    function CheckValidationStatus(sender, args) {
        //Check if the form is valid; this validation state is stored in a form hidden field.
        if($("#formIsValid").val() == "false") {
           //if the form is not valid,  then cancel the async postback
           args.set_cancel(true);
        }
    }

    Add the Form Hidden Field

    Since the ASP.NET Web Forms development allow only for one single HTML form inside the page, just place a new HTML hidden field next to the HTML form.

    <form id="form1" runat="server">
      <
    input type="hidden" name="formIsValid" id="formIsValid" value="false" />

    This hidden field is going to keep the form validation state: [true|false]. The Ajax async. post-back would be aborted when this field would be “false”.

    Setup jQuery Validation

    Add the regular jQuery validation routine: the submitHandler is triggered when the validation is successful, and it must set “true” for the formIsValid hidden field: to continue performing the Ajax async post-back.

    function pageLoad() {
         $("#formIsValid").val("false");
         $("form").validate({
              submitHandler: function() {
                  $("#formIsValid").val("true"); 
             }
         });
       }

    The ASP.NET Ajax pageLoad() function is being called by the ASP.NET Ajax on the web page first load, but also on each async postback, therefore the validated fields are registered again, after the partial postback.

    The UpdatePanel With the Data Entry Form

    This is a sample data entry form, hosted inside an ASP.NET Update Panel.

    <asp:UpdatePanel ID="ContentUpdatePanel" runat="server">
         <ContentTemplate>
           <div
             <
    label>Username</label><asp:TextBox ID="UsernameTextBox" runat="server"  CssClass="required"></asp:TextBox><br />
             <label>Email</label><asp:TextBox ID="EmailTextBox" runat="server" CssClass="required email"></asp:TextBox><br />
             <asp:ButtonID="SubmitButton"runat="server" OnClick="SubmitButton_Click" Text="Submit" CssClass="submitButton" /> 
           </div>
         </ContentTemplate>
      </asp:UpdatePanel>

    As we seen so far, jQuery is a great library to be used for client side scripting, and the jQuery validation plug-in is really useful, when it comes to get UI validation done quick, safe and fun.

    luni, 2 noiembrie 2009

    Coming soon

    Great free articles and tutorials about ASP.NET Development and advanced techniques.

    Coming soon...