.NET Performance Blog

April 5, 2011

OpenFaq (Part 3): Custom Membership Provider in Entity Framework Code First

Filed under: ASP.NET MVC,BDD,DDD,General,TDD — Eric P @ 4:33 am

Previous posts in OpenFaq series
OpenFaq (Part 1): The beginning
OpenFaq (Part 2): Business Requirements in Code
Source code in Codeplex
http://openfaq.codeplex.com/SourceControl/list/changesets

Why Custom Membership Provider

When creating new MVC web site – it is automatically configured to use SqlMembershipProvider. Before it can actually be used, the default tables need to be created in DB using spnet_regsql.exe tool here.
http://www.asp.net/security/tutorials/creating-the-membership-schema-in-sql-server-vb.
That creates a whole bunch of tables, views and stored procs. See link above.

I would like to be pretty consistent in my approach to how the database is accessed (through Entity Framework) and how my tables are named and structured. So I am going to use a flexible Provider model supplied my mine and your friends at Microsoft to implement a custom membership provider that will be driven by Code First Entity Framework.

YAGNI says only to implement things I need and worry about “things I don’t need” when I need them. So at this point in my application I just want to be able to register users, log them in and possibly change their password.

The acceptance tests written in part 2 of this series should still work.

Getting Samples from the Holy Book of MS (MSDN)

I used several examples provided by Microsoft for guidance:
http://msdn.microsoft.com/en-us/library/6tc47t75.aspx – simple example of ODBC Membership provider (C# after VB.NET code)
http://msdn.microsoft.com/en-us/library/aa478948.aspx – toolkit that includes fully featured example of Sql Membership/Role/Profile providers

A couple of interesting discoveries during implementation.

1. Some business logic code that should be re-usable is not provided in base MembershipProvider class

Two major cases of this were:
– Password Validation – like checking that password must be greater then 6 chars
– Password hashing – using Clear/Encrypted/Hashed

Both samples from Microsoft implement their own versions of validation and hashing.
In my case I had to implement my own (mostly by copying the toolkit sample).

I was hoping that provider model would allow to override these scenarios, but provide basic implementation which would be applicable in 90% of the cases.
Unfortunately that’s not the case.

2. Bad coding practices in sample

In Tooklit example there were a couple of things, that would make some developers punch the wall with their head.

The “Code Duplication” is the only major one, but since many developers are looking to microsoft for guidelines on how to write good code, I think MS should really make sure that their code has been properly reviewed and updated whenever there are new .NET features and guidelines. For ex. ODBC Membership provider sample is still using Hungarian notation which MS has been saying not to use for a while now.

Here are some examples of bad coding practices from Toolkit sample:

Code Duplication

Password validation logic is duplicated in CreateUser and ChangePassword

-- In CreateUser

           if( password.Length < MinRequiredPasswordLength )
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }

            int count = 0;

            for( int i = 0; i < password.Length; i++ )
            {
                if( !char.IsLetterOrDigit( password, i ) )
                {
                    count++;
                }
            }

            if( count < MinRequiredNonAlphanumericCharacters )
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }

            if( PasswordStrengthRegularExpression.Length > 0 )
            {
                if( !Regex.IsMatch( password, PasswordStrengthRegularExpression ) )
                {
                    status = MembershipCreateStatus.InvalidPassword;
                    return null;
                }
            }

            string salt = GenerateSalt();
            string pass = EncodePassword(password, (int)_PasswordFormat, salt);
            if ( pass.Length > 128 )
            {
                status = MembershipCreateStatus.InvalidPassword;
                return null;
            }


-- In ChangePassword
  

            if( newPassword.Length < MinRequiredPasswordLength )
            {
                throw new ArgumentException(SR.GetString(
                              SR.Password_too_short,
                              "newPassword",
                              MinRequiredPasswordLength.ToString(CultureInfo.InvariantCulture)));
            }

            int count = 0;

            for( int i = 0; i < newPassword.Length; i++ )
            {
                if( !char.IsLetterOrDigit( newPassword, i ) )
                {
                    count++;
                }
            }

            if( count < MinRequiredNonAlphanumericCharacters )
            {
                throw new ArgumentException(SR.GetString(
                              SR.Password_need_more_non_alpha_numeric_chars,
                              "newPassword",
                              MinRequiredNonAlphanumericCharacters.ToString(CultureInfo.InvariantCulture)));
            }

            if( PasswordStrengthRegularExpression.Length > 0 )
            {
                if( !Regex.IsMatch( newPassword, PasswordStrengthRegularExpression ) )
                {
                    throw new ArgumentException(SR.GetString(SR.Password_does_not_match_regular_expression,
                                                             "newPassword"));
                }
            }

            string pass = EncodePassword(newPassword, (int)passwordFormat, salt);
            if ( pass.Length > 128 )
            {
                throw new ArgumentException(SR.GetString(SR.Membership_password_too_long), "newPassword");
            }
            ...

The logic from both functions should be combined into one method like ValidatePassword, which returns enough information to generate proper exception or return error code in calling function.

Using try/catch with no logic in catch

Throughout the toolkit sample there is code like

try {
               //some code
} catch {
                throw;
            }

If you ever stumble over code like above, I would recommend rewriting it like this and then sending it to original coder for review:

DoNothing();
//some code
DoNothing();
DoNothing();
DoNothing();


private void DoNothing()
{
     //Do nothing
}  

On the bright side, it is not as bad as

try {
               //some code
} catch {
              //do nothing, to make sure that no exceptions are ever visible to user or the poor poor developer who will be maintaining this code
}

but nothing really is…

functions that have 10 input and 10 out parameters

   private void GetPasswordWithFormat( string       username,
                                            bool         updateLastLoginActivityDate,
                                            out int      status,
                                            out string   password,
                                            out int      passwordFormat,
                                            out string   passwordSalt,
                                            out int      failedPasswordAttemptCount,
                                            out int      failedPasswordAnswerAttemptCount,
                                            out bool     isApproved,
                                            out DateTime lastLoginDate,
                                            out DateTime lastActivityDate)

Uncle Bob just started spontaneously crying…

Not sure when this sample was written, but unless it was written on punch cards, they must have heard about passing in and returning structures, instead of 10+ args.
Also things like single responsibility principle – why does function called GetPasswordWithFormat return lastLoginDate.

Implementing the beast

From business requirements perspective, at this point I would like to support:
Register
Login
Change password

So I implemented the following functions in new CustomMembershipProvider class:
CreateUser
ValidateUser
ChangePassword

Naming Unit Tests

For each function that I implemented in CustomMembershipProvider I created unit tests first.
I used format
{Function}_With{Description}_Should{Result}
for ex…
CreateUser_With_Valid_Data_Returns_User()

Then I found a nicer format:
[MethodName_StateUnderTest_ExpectedBehavior] from:
http://stackoverflow.com/questions/155436/unit-test-naming-best-practices

So the previous example is now:
CreateUser_WithValidData_ReturnsUser()

I also wanted to include “given” conditions (used in BDD), so it would be:
CreateUser_GivenDefaultMembershipProvideSettings_WithValidData_ReturnsUser()

At the end I changed “With” to “When”, so that we would use the same language for both BDD and TDD and I ended up with:
{Function}_Given{Precondition1}_Given{Precondition2}_When{Action}_{Result}
so example would be:
CreateUser_GivenDefaultMembershipProviderSettings_WhenValidData_ReturnsUser

Here are all the unit tests that should demonstrate what is currently implemented, for your viewing pleasure:

		[TestMethod]
		public void CreateUser_GivenDefaultMembershipProviderSettings_WhenValidData_ReturnsUser();

		[TestMethod]
		public void CreateUser_GivenPasswordRequiresMin6Chars_WhenPasswordHasLessThen6Chars_ReturnsNullAndStatusInvalidPassword();

		[TestMethod]
		public void CreateUser_GivenPasswordRequiresMin6Chars_WhenPasswordHasMoreThen6Chars_ReturnsUser();

		[TestMethod]
		public void CreateUser_GivenPasswordRequiresOneNonAphaNumericCharacter_WhenPasswordHasNoNonAlphaNumericCharacters_ReturnsNullAndStatusInvalidPassword();

		[TestMethod]
		public void CreateUser_GivenPasswordRequiresOneAphaNumericCharacter_WhenPasswordHasOneAlphaNumericCharacter_ReturnsUser();

		[TestMethod]
		public void CreateUser_GivenPasswordRequiresMatchRegularExpressions_WhenPassswordNotMatchingRegularExpreation_ReturnsNullAndStatusInvalidPassword();

		[TestMethod]
		public void CreateUser_GivenPasswordRequiresMatchRegularExpressions_WhenPassswordMatchingRegularExpreation_ReturnsNullAndStatusInvalidPassword();

		[TestMethod]
		public void CreateUser_WhenUsernameNotUnique_ReturnsNullAndStatusDuplicateUserName();

		[TestMethod]
		public void CreateUser_GivenPasswordFormatHashed_HashesPassword();

		[TestMethod]
		public void ChangePassword_WhenValidArguements_ChangesPassword();

		[TestMethod]
		public void ValidateUser_WhenUserWithUsernameAndPasswordExists_ReturnsTrue();

		[TestMethod]
		public void ValidateUser_WhenUserWithUsernameAndPasswordDoesNotExist_ReturnsFalse();

Deep Thoughts

In this episode of OpenFaq (The Series), we looked at how to create a simple Custom Membership Provider that uses EF Code First for back-end.
Coding crimes committed by MS where brought to light with appropriate punishment being administered as we speak.
TDD and BDD is still being followed.

For now you can get all the code discussed in this post from here:
http://openfaq.codeplex.com/releases/view/63833

Coming up next…

Now that we have the basic framework down, we are gonna implement us some FAQ goodness…

Current project road map is here:
http://openfaq.codeplex.com/wikipage?title=Road%20Map%20%26%20Progress

Advertisements

March 27, 2011

OpenFaq (Part 1): The beginning

Filed under: .NET,ASP.NET,ASP.NET MVC,DDD,General,TDD — Eric P @ 1:43 pm

It is time to learn some new technologies.

For this task I am going to write FAQ applicaton called OpenFaq.

OpenFaq – The future of FAQ

Whenever we buy any new product there is usually some questions or issues that come up, that may not be covered in manual or by asking the uncle who (supposedly) knows everything. How do I …? Why am I getting this f#$x error? etc…

In some cases you may go to product’s website and try to find an answer there. In about 5 minutes (depending on how quickly you reach the boiling point) you give up and just do a google search.

Why are so many sites so bad in helping you find what you need?

The problem(s) this application will try to solve is:
On many sites FAQ is created early on and not frequently updated. It quickly becomes forgotten.
The questions are grouped according to how website administrator feels like they should be grouped. Not based on frequency of asking.
User interaction is limited to reading an answer

The Solution
Make FAQ dynamic, so admin can edit questions and answers without doing rollout
Get users involved with asking, answering, voting and comments (similar to stack overflow)
Use voting and other statistics to determine which questions are frequent/popular and which are not

Some Business Requirements

Some preliminary requirements for this application are:
* User can login
* User can post question
* User can answer question
* User can comment on question and answer
* User can vote on question and answer
* User can use keyword search to quickly find questions, answers

Maybe a touch of Technology

In this series I will try out some new technologies from MS and use some of the latest methodologies in application development.

For a while now I have been reading about many new technologies and approaches for software development. Here is the list that I plan to use for OpenFaq.

Approaches

  • BDD – behavior driven development
  • TDD – test driven development

Principles

  • YAGNI – you are not going to need it
  • KISS – keep it simple stupid
  • DRY – don’t repeat yourself

Technology

For this project I am going to use Microsoft stack.

  • ORM – EF 4 Code First
  • Web Framework – MVC 3
  • Template Engine – Razor
  • Package/Dependecy Manager – NuGet
  • BDD – SpecFlow
  • UI Testing/Acceptance test – WatiN
  • Unit testing – MS Test
  • Version Control – Mercurial
  • Project Site – Codeplex.com

January 29, 2009

OOP vs Structured/Procedural programming (or DDD vs ADM)

Filed under: DDD,General — Eric P @ 12:26 pm

I think I may have succeeded in creating a headline with most Jargon evar… It is almost as bad as the name of my blog.

I have been having this dilemma. I have an enterprise level application written using OOP and ActiveRecord. It utilizes many OOP concepts such as Inheritance and Polymorphism. Recently I have been looking into making the system more friendly for Unit Testing. I talked about it to some developers working on the system and I had an interesting revelation: most of the developers prefer Structured/Procedural programming over OOP.

Here is the general overview of Procedural programming and OOP.
From http://www.umsl.edu/~subramaniana/concepts1.html

Procedural/Structured programming

  • Procedural Approach Data Structures can be represented as a network of associated structures, referring to one another.
  • Procedures can be represented as a network of routines which call one another, i.e., “call tree”

OOP

  • Object Oriented Approach Collection of discrete objects that incorporate data structures and behavior.
  • Each data structure has, combined with it, the procedures which apply to that data structure.
  • Contrasts with conventional programming in which data structures and behavior are only loosely connected
  • These entities, called objects, can be associated to one another in one network, rather than two.

DDD is based on OOP, while Anemic Domain Model is all about procedural programming.

Back to Dilemma. As much as Anemic Domain Model is an anti-pattern – it has one really nice thing going for it – it is simple and it makes sense to most developers and non-developers. How can Order ship itself, how can cake bake itself? Instead order and cake are just data and you have some OrderService and CakeService operating on them. With SOA even many business people can easily think in procedural terms.

My current system is written using OOP – objects have both data and actions. So I was hoping that switching to DDD would make OOP even more central to future development. The problem is that separating Active Record Entities into Repositories, Domain Entities and Application Services layer is confusing other developers on my team. Many of them come from procedural programming (aka Java EJB), so as soon as they see Entities and Services – then all logic goes into Services while Entities are just data structures.

Here is an example of what I have in my system:


Order
{
     OrderStatus _status;  (InProgress, Paid, Shipped)
     List _orderLines;
     
     Customer _customer;
     OrderBilling _billing; //Includes ShippingAddress and payment info
     OrderShipping _shipping;  
      
     DateCreated _dateCreated;
    
     AddOrderLine(product, quantity)
     RemoveOrderLine(orderLine)

     CalculateTotal();

     TakePayment();
     Ship();
}

Here is the same code written using ADM/Procedural:


Order
{
     OrderStatus _status;

     List _orderLines;
     Customer _customer;
     OrderBilling _billing;
     OrderShipping _shipping;  //Includes ShippingAddress and payment info
     DateCreated _dateCreated;
}


OrderService
{
     AddOrderLine(order, product, quantity)
     RemoveOrderLine(order, orderLine)
     
     CalculateTotal(order);

     TakePayment(order);
     Ship(order);
}

So what are the benefits of OOP vs ADM:
1. In OOP all the methods that operate on Entity are part of entity (or delegated to appropriate command/domain services by entity), while in Procedural – the code can be dispersed through many different services.

2. OOP is better for code re-use. Will need some examples for this one.

3. When refactoring, can use OOP Design Patterns like State Pattern for switching Order status.

But saying all this is not enough. There is only one way to make a convincing argument in Software Development:

SHOW ME THE CODE

In the upcoming blog entries, I will try to provide a real world coding example for each one of the points above…

Create a free website or blog at WordPress.com.