Dot Net

Syrinx .NET Development Blog
Need help on your project? info@syrinx.com, or toll free (888) 579-7469, press 1

February 2008 - Posts

A Simple Custom Sql Membership Provider Part 2

In A Simple Custom Sql Membership Provider Part 1, I talked about how to create a new Sql Membership Provider in order to modify the behavior of the default provider, without having to write your own provider from scratch. 

In this part, I'll show you how to further extend the provider to give the appearance of case-insensitivity for passwords.  Please note, when passwords are configured to be hashed (not retrievable), you cannot provide true case-insensitivity.

To provide the desired behavior, we can essentially force all passwords to lowercase.  We need to do this when they are set initially, when they are reset, when they are changed, and when they are validated during login.  Any gaps in this logic may result in the inability to login.

Here is the code to do this...

private bool CaseSensitive;

string CaseSensitiveConfig = config["caseSensitive"];
if (CaseSensitiveConfig != null)
{
    // Have to remove the config entry as the provider we are 
    // inheriting from doesn't understand it and will throw an 
    // exception
    config.Remove("caseSensitive");
     if (!bool.TryParse(CaseSensitiveConfig, out CaseSensitive))
    {
        // Have to reset to default as TryParse will set it to 
        // false if the value can't be parsed
        CaseSensitive = true;
    }
}
else
{
    // Default to case sensitive
    CaseSensitive = true;
}


#region Override Password logic for case-insensitive functionality
//Override the default logic for creating users, changing passwords,
//and logging in; in order to give the effect of case-insensitivity.
// For every call that uses password, force the user input to lower case
//as well.
//Although this is configurable via the provider's configuration 
//section, this setting should not be changed after users have been
//live on the system.  If any passwords get into the system with 
//upper case characters, that user will be unable to login.

public override bool ChangePassword(string username, 
    string oldPassword, string newPassword)
 {
    if (!CaseSensitive)
    {
        oldPassword = oldPassword.ToLower();
        newPassword = newPassword.ToLower();
    }
    return base.ChangePassword(username, oldPassword, 
        newPassword);
}

public override MembershipUser CreateUser(string username, 
    string password, string email, string passwordQuestion, 
    string passwordAnswer, bool isApproved, object providerUserKey, 
    out MembershipCreateStatus status)
{
    if (!CaseSensitive)
    {
        password = password.ToLower();
    }
    return base.CreateUser(username, password, email, passwordQuestion, 
        passwordAnswer, isApproved, providerUserKey, out status);
}

public override bool ValidateUser(string username, string password)
{
    if (!CaseSensitive)
    {
        password = password.ToLower();
    }
    return base.ValidateUser(username, password);
}
#endregion
Design By Contract (DBC)

I want to discuss a concept I first read about when going through the "Pragmatic Programmer" book. By the way this is an awesome book I recommend for every programmer. The book has tons of nuggets of helpful tidbits that every developer will find useful.

The term Design By Contract (DBC) is a term coined by Bertrand Meyer in connection with the Eiffel programming language but can be applied  to any object oriented programming language including .NET. although not as elegantly as Eiffel since DBC is built right into that language. It is a technique that focuses on documenting and agreeing to the rights and responsibilities of software modules to ensure program correctness - doing no more or no less than a program claims to do. The documentation and verification is at the heart of Design by Contract.

Every method has some functionality. The method may have some expectation of the state of the world before it is called as well as make some conclusion about the state of the world after being called. The 3 components of DBC is as follows:

Preconditions: These must be true in order by the routine to be called: These form the conditions or obligations to be guaranteed on entry by any client module that calls the method. A routine should thus never be called when its preconditions would be violated. It is the caller's responsibility to pass good data or set the conditions required before calling the routine.

Post Conditions: This describes what the routine is guaranteed to do and this describes the state of the world when the routine is done. This in essence describes what the callee is expected to do and what the caller should expect after calling the routine.

Class Invariants: A class ensures that this condition is always true from the perspective of the caller. While processing the routine, this invariant may temporarily not hold, but by the time the routine exits and returns control, the invariant must be true.


The contract between a routine and any potential caller can thus be read thus:
If all the routine's preconditions are met by the caller, the routine shall guarantee that all post conditions and invariants will be true when it completes.


Below is a DBC example of a routine that inserts a data value into a unique ordered list. In the example below:

public void insertNode(Node aNode)

The precondition might be that it does not already contain aNode i.e. Contains(aNode) == false;
Post condition might be that it will contain aNode i.e. Contains(aNode) == true;
The invariant could be
    foreach( Node n in nodes)
        if ( node.Prev() != null ) {
          Implies that (  n.value CompareTo (n.Prev().value) > 0 )


 A failure of the precondition indicates a bug in the caller, the client. A failure of the postcondition indicates a bug in the routine, the supplier. These conditions, or specifications, are implemented by assertion statements. In C/C++ code the assert macro is used for these purposes. The .NET Framework Class Library uses assertion functions available in the System.Diagnostics  namespace. By default these generate an "abort, ignore, retry" message box on assertion failure. These assertions should not have side effects.
Unlike Effiel which has DBC built into the language, C# implements DBC via assertions or exception handling.
The library provides a set of static methods for defining preconditions, postconditions, class invariants and general assertions and the exception classes that represent them. Methods are also provided that invoke the .NET  System.Diagnostics.Trace() assertions as an alternative to throwing exceptions.

The implementation of the DBC for C# could be such.

public void insertNode( Node aNode) {
    // precondition
     Trace.Assert( nodes.Contains(aNode) == false )

   ... code logic to insert the node into the list in a unique ordered fashion

   //  post condition
   Trace.Assert( nodes.Contains(aNode) == true )

}


The invariant can be tested by the caller of the routine.
foreach( Node n in nodes)  {
  if ( node.Prev() != null ) {
      Trace.Assert (  n.value.CompareTo (n.Prev().value) > 0 )
  }
}


If either party fails to live up to the terms of the contract then a remedy ( which was previously agreed to ) is invoked - an exception is raised or the program terminates for instance.

CAB - Composite Application Block
   I recently had a chance to work on a project for a client using CAB, which stands for Microsoft’s Composite Application Block. The framework offers quite a few nice features that help with creating applications that are complex and big. But the biggest culprit that I see with it is that it may be a little on the high learning curve side. Once you get your hands on the included samples and start coding it things will get better and start ticking.

  
CAB introduces the workitem, smartpart and workspace classes, these are classes that are mainly used for UI management. SmartParts are just your view/userontrol wrapped in a fancy CAB terminology. However the CAB framework encourages the use of the MVP pattern (Model View Presenter). Which I think is a plus, since it makes unit testing easier in addition to the better code abstraction that it provides. Btw, I do not think MVP is a fancy name for code behind as some others might think it is, but that is something I want to talk about at another time. Next is the workspace, which is a usercontrol that is used as a placeholder within the form, so that we can put smartparts in it. Workspaces provide functionality to interchange smartparts, provide them in a tabbed style or dock them in a certain fashion. Then we have the workitem, its main responsibility is to manage a use case which is an important concept in CAB. In CAB business requirements are broken down into use cases which are implemented as workitems.  In addition, it is also responsible for the creation and management of smartparts which are used to carry out the use case requirements.

  
Another important CAB concept is the event broker, the event broker allows objects such as the workitem and smartpart to communicate without any direct references. As a result assemblies will not have referential constraints like other some other designs. Which can ease development efforts since we can have multiple teams working on different sections (use cases) of the application. There are a few other CAB features that I did not get a chance to fully utilize since the project that I worked on did not require it, such as the state injection and command features. For more info on CAB I suggest visiting the CAB website on CodePlex at http://www.codeplex.com/smartclient, it contains a forum with a good community of  developers sharing there knowledge and experience on this wonderful framework.

GaryY