About the author

J Sawyer is a developer based in Houston, TX and loves to write code, especially ASP.NET and other web-related stuff. He is currently working on implementing Team Foundation Server at a large energy company in Houston and is loving that too.

He also loves to ride his Yamaha FZ1. And sometimes his Ninja 650.

But he doesn't code and ride at the same time. That would be bad.

CSK 3.0 CTP1

November 3, 2008 6:36 PM

I know, I know, it’s a little late. I said Nov 1st and it’s now Nov 3rd. Here’s what happened – I was all on track to have it ready for the 1st, but then I got sick. I felt like a bowl of cold oatmeal, which is not very good. Kids … I’m tellin’ ya … they’re germ factories. I wound up spending the weekend in bed, resting. I could have down a drop on Friday or Saturday regardless, but it wasn’t at the point that I wanted it to be. Now that I’m feeling better, I got back down to it and got it to the point that I wanted in about an hour or so worth of work (told you I was close).

[EDIT] You can download it from CodePlex. (thanks Alan!)

Release Notes

This is a Tech Preview. Read: nowhere near final. It’s not even up to what I’d call a beta. I’m putting this up primarily for feedback from the community and (hopefully) to generate some additional interest. It does show the direction that I’m going with this and I hope you’ll notice that, while the underlying functionality is pretty complex, it’s easy to work with and easy to change the UI. I have avoided duplicated any code as much as possible, though I may have missed something.

User Interface elements:

Most of the user interface is encapsulated in User Controls, which you will find in the Controls folder. I think that the names should be self-explanatory. For simplicity, data binding is used whenever feasible. Yes, it is not the most attractive. If there is anyone with better design skills, I’d be happy to hear from you.

Implemented functionality:

It’s the very base functionality; you have catalog display and navigation, cart functionality and checkout functionality. Checkout does not, at this time, call any of the payment processing components but the code will be (for the most part) the same when that does get added in.

Installation:

Unzip the file to a folder on your system. In the Data folder, you will find a backup of the Sql Server database that is used for the site. If you restore this to “.\SqlExpress” in a database named “CommerceDb”, you will not need to make any changes at all to the connection strings. If, however, your database is different, change the connection strings that are in the web.config.

Coming next:

Added actual payment processing. Would like to get login implemented as well; we’ll see about that.



Tags: , ,

CSK | Open Source | Web (and ASP.NET) Stuff

Commerce Starter Kit 3.0 – CSK Reprise

October 24, 2008 5:59 PM

I am happy to announce a new Commerce Starter Kit. We’re calling it CSK 3.0, but it’s not based on the previous (CSK 2.0) codebase at all; it is a complete re-write from the ground up. Some of you probably remember when I first got involved in the CSK … that was WAAAAAY back in the days when ASP.NET 2.0 was all new and shiny. ASP.NET has, of course, moved forward quite a bit since then. We won’t be just upgrading the old CSK code base, but building a brand-spanking-new version, even though we’ll be calling it CSK 3.0. And … it will be in the same spirit as CSK - “shared source” and freely available to all. I will be reporting progress on this regularly, so you will want to subscribe if you want all the latest updates and news on the project.

This all started with a chat or two with my old buddy Rob Conery, the creator of the original Commerce Starter Kit. He’s here at Microsoft now and working on the MVC Storefront, a sample application that uses the ASP.NET MVC Framework (as the name implies). At the end of these chats, we thought we’d revive the CSK name and build a new version … with components and business logic based on the same components and business logic used for MVC Storefront but with a traditional WebForms UI. That’s right folks … it’s gonna share code with the site that Rob’s working on. Not only does it make life much easier, it also shows how the same core logic and functionality can be skinned with either MVC or WebForms.

Here’s the core stuff that is on the plate for this version:

Updates to the latest coolness: CSK 3.0 will be targeting ASP.NET 3.5 with SP1, so we’ll have all of the latest toys, including (of course!) Linq. :-)

Migration to common e-Commerce libraries: I mentioned this above; CSK will be using the same core business libraries and database as MVC Storefront, allowing you to easily switch between the two.

Localization support: Oh boy, I remember lots of folks asking for this with CSK 1.x and 2.0. The new CSK will be localizable out of the box. All of the product and category text and descriptions will be localizable. The goal is to also have most, if not all, of the static text on the pages localizable as well. That’ll be fun with resource files.

ASP.NET Dynamic Data Administration: The admin site will now be a separate web application so that there’s better isolation from the main web site. Of course, this could be installed as a virtual directory application under the main site but that won’t be necessary at all. You’ll easily be able to deploy it as a completely separate web site.

ASP.NET Web Application: This is the “old” (as in 1.x) model for web applications. While it’s not as easily changed while running (since you actually have to do a build), it does provide better start-up performance, something that became a complaint with CSK 2.0. Yes, yes, you could pre-compile the site (and I often suggested that folks do this) but with the web application model, that won’t be a separate step.

ASP.NET Ajax: This is all a part of the cool new toys, but I thought I’d highlight it separately. We’ll be using ASP.NET Ajax where it makes sense as well as the ASP.NET Ajax Control Toolkit.

Better composability: One of the things that I thought we could have done better with CSK 2.0 was to have a better composition model for the UI … for example, there were 2 or 3 different places to change a product list display … category list, search list, etc. This made it more difficult to maintain as fields were added or changes were made to certain core UI elements. These components will be separated into a series of User Controls, each with distinct, composable functionality. You want to change the view of a product in a list? Change it once and you’ll see it everywhere … search results, category listing, cart, etc.

Coupons: This was only partially implemented in CSK 2. Rob and I spent a couple of hours, both on the phone and over IM, and forth on how this would be implemented and I think it’s settled. The coupon system is going to be very extensible so that you can create any type of coupon that your heart desires. We’ll be including a couple of simple ones to get you started.

One of my key goals with this rev is simplicity. I want the UI (at least) to be as simple as possible … and I want it to be simple to re-skin the CSK to your own look and feel. To that end, I am using quite a bit more controls and data binding than were used in version 2.0 … everything, in fact, is in some sort of control or another. Additionally, I do want to highlight, as much as possible, the infrastructure of ASP.NET as well as the extensibility of this infrastructure. For example, for the category listing, I’m using a SiteMapProvider that builds a site map from the categories in the database. Believe it or not, this is actually quite easy to do and provides things like the SiteMapPath, which I do plan on getting in there.

I will need some help with this – in particular, I’d really like help with the following:

  • Functionality – what features are essential and/or cool? What do you want to see in there? (No guarantees that it’ll make it, but if you offer to do it, it’s a lot more likely!)
  • Design – Right now, I’m just stealing the design and layout from the MVC Storefront, converting it to use WebForms (so no MVC calls), etc. etc. etc. I call it the CASE methodology – Copy Always, Steal Everything. Now, I have the design skills of a dead toad, so redoing the design is simply out of the question. BUT … I would like to see it begin to diverge from MVC Storefront’s look. So any help that you might want to provide to do that would be very nice.
  • Testing – Yes, we’ll have automated tests to catch a bunch of stuff, but manual testing and feedback is also needed, particularly when it comes to user experience.
  • Migration – From CSK 2. I really don’t know if this is going to actually be possible and it’s certainly not something that I have on the list of “stuff to do” but if someone wants to volunteer to write a migration utility, that’d be cool with me.

I’m targeting to get the first, alpha “preview” version out in the next week or so and I’ll announce that here as well.



Tags: , ,

CSK | Open Source | Web (and ASP.NET) Stuff

.NET Dojo: ASP.NET MVC

July 22, 2008 7:37 PM

First, what's this .Net Dojo stuff? Well, here it is ... it is a new series of events (I'm hoping monthly) that we will be having monthly to help developers hone and sharpen their .Net Kung Fu. It will be a combination of lecture and hands-on labs ... lecture to explain the concepts (of course) and hands-on to let you get your fingers dirty playing with the technology. Since it is hands-on, you will need to bring a laptop to do the labs and (possibly) install some additional prerequisites before the session (these will be listed, of course). They will be held at the Houston Microsoft office from 1:00 PM to 5:00 PM and cover a wide range of .Net topics. I'm also hoping to be able to get some of the technical leaders here in Houston to deliver some of the sessions ... so that you'll be learning from the best around.

Ben Scheirman of Sogeti has volunteered to deliver the very first .Net Dojo on the ASP.NET MVC Framework. (Didn't I tell you that I wanted to get the best around?) Here are the details:

Overview: ASP.NET MVC is one of the key new features that will be included in .NET Framework 3.5 Service Pack1. It provides a framework that enables you to easily implement the model-view-controller (MVC) design pattern in your web applications, helping you build loosely-coupled, pluggable components for application design, logic and display. While not a replacement for traditional ASP.NET WebForms, ASP.NET MVC does provide a compelling alternative for developing web applications and better facilitates test driven development (TDD) in web applications. This workshop will dig into what ASP.NET MVC is, what it does, and how it is different from WebForms.

What you will learn: Through a combination of lecture and hands-on labs, attendees will learn how to create ASP.NET MVC applications using Visual Studio 2008 and how to work with the key components of an ASP.NET MVC application. Additionally, they will learn how to test their MVC components and applications using TDD principles.

Prerequisites: To fully participate in this workshop, attendees will need the following:

  • An open mind
  • A working knowledge of ASP.NET, C#, HTML and CSS.
  • A laptop with:
    • Visual Studio 2008 Professional or higher (Trial is OK)
    • ASP.NET MVC Preview 4 (available as a separate download.
    • A CD-ROM drive to load additional components and lab files.

Sign up here ... but hurry ... space is limited!

Hope to see you there ...

Tags: , ,

.NET Stuff | Events | Web (and ASP.NET) Stuff

C# SIG Presentation

July 22, 2008 11:59 AM

I have uploaded (finally) the presentation that I delivered to the C# SIG last Wednesday, July 16 to my SkyDrive. You can download it here.

I did make some little modifications to it though ... and they address one of the outstanding questions of the evening ... how does ASP.NET Role-based security work with ASP.NET Dynamic Data? Well, it's pretty simple and straightforward, actually.

Some background first. ASP.NET Dynamic Data uses SP1's UrlRoutingModule to map requests to the correct table ... with the name of the table appearing as a directory on the web site. So, when editing the "Products" table, the URL will be http://mydatasite/Products/[NameOfView]. Adding authentication and authorization for the entire site is a no-brainer; just add the authorization element into the web.config with the proper entries and you're done. Doing it for individual tables is just about as easy; in this case, you just need to add a location element to your web.config and configure the settings for the location. For example:

<location path="products">
  <system.web>
    <authorization>
      <allow roles="Products"/>
      <deny users="*"/>
    </authorization>
  </system.web>
</location>

In this case, we have defined a role called "Products" that can edit (and view, of course) the products table, but no one else can. This will behave exactly as would a "real" folder in any ASP.NET web site using role-based authorization with the built-in RoleManager (regardless of where the roles are actually coming from!).

As I said, I added this to the demos that I uploaded. All access to the site is authenticated; no anonymous users are allowed. There are 2 roles - Products, which can edit the Products table and HR, which can edit the Employees table - and 3 users. All users have the same password (Pass@word1). Here's the breakdown:

User ID Role
User1 HR
User2 Products
User3 <No Role>

 

You can, of course, get a bit more complicated than this, but you'd have to do some additional customization of the different pages to do that.



Tags: , ,

Community | User Groups | Web (and ASP.NET) Stuff

New Account Email Validation (Part II)

June 25, 2008 8:39 PM

In my previous post, I discussed the things to keep in mind with new account validation. Well, as promised, I've done a sample of one way to do this.

Certainly step 1 to to do as much as possible without writing any code, following the KISS principle. Since I am using the CreateUserWizard Control, I set the DisableCreatedUser property to true and LoginCreatedUser to false. Easy enough. But that's not the whole story. We need to generate the actual validation key. There are a lot of ways that one can do this. Personally, I wanted, as much as possible, to not have any dependency on storing the validation code in the database anywhere. This, of course, ensures that, should our database be penetrated, the validation codes cannot be determined. With that, then, the validation code should come from data that is supplied by the user and then generated in a deterministic way on the server. Non-deterministic, of course, won't work too well.

I started down (and really, almost completed) a path that took the UserName and Email, concatenated them, generating the bytes (using System.Security.Cryptography.Rfs2898DeriveBytes) to create a 32-byte salt from this. I again concatenated the UserName and email, then hashing it with SHA1. This certainly satisfied my conditions ... the values for this would come from the user and so the validation code didn't need to be stored. And it was certainly convoluted enough that a validation code would be highly difficult to guess, even by brute force. In the email to the user, I also included a helpful link that passed the validation code in the query string. Still, this code was some 28 characters in length. Truly, not an ideal scenario. And definitely complex. It was certainly fun to get the regular expression to validate this correct ... more because I'm just not all that good at regular expressions then anything else. If you are interested, the expression is ^\w{27}=$, just in case you were wondering.

Thinking about this, I really didn't like the complexity. It seems that I fell into that trap that often ensnares developers: loving the idea of a complex solution. Yes, it's true ... sometime developers are absolutely drawn to create things complex solutions to what should be a simple problem because they can. I guess is a sort of intellectual ego coming out ... we seem to like to show off how smart we are. And all developers can be smitten by it. Developing software can be complex enough on its own ... there really is no good reason to add to that complexity when you don't need to. There are 3 key reasons that come to mind for this. 1) The code is harder to maintain. Digging through the convolutions of overly complicated code can make the brain hurt. I've done it and didn't like it at all. 2) The more complex the code, the more likely you are to have bugs or issues. There's more room for error and the fact that it's complicated and convoluted make it easier to introduce these errors and then miss them later. It also makes thorough testing harder, so many bugs may not be caught until it's too late.

So, I wound up re-writing the validation code generation. How did I do it? It's actually very simple. First, I convert the user name, email address and create date into byte arrays. I then loop over all of the values, adding them together. Finally, I subtract the sum of the lengths of the user name, password and creation date and subtract from the previous value. This then becomes the validation code. Typically, it's a 4 digit number. This method has several things going for it. First, it sticks to the KISS principle. It is simple. There are very few lines of code in the procedure and these lines are pretty simple to follow. There are other values that can be used ... for example, the MembershipUser's ProviderKey ... when you are using the Sql Membership provider, this is a GUID. But not depending on it gives you less dependence on this. Second, it is generated from a combination of values supplied by the user and values that are kept in the database. There is nothing that indicates what is being used in the code generation ... it's just a field that happened to be there. This value is not as random as the previous, I know. It's a relatively small number and a bad guy could likely get it pretty quickly with a brute-force attack if they knew it was all numbers. To mitigate against this, one could keep track of attempted validations with the MembershipUser using the comments property, locking the account when there are too many attempts within a certain time period. No, I did not do this. Considering what I was going to use the for (yes, I am actually going to use it), the potential damage was pretty low and I felt that it was an acceptable risk. Overall, it's a pretty simple way to come up with a relatively good validation code. And it's also very user-friendly. Here's the code:

public static string CreateValidationCode(System.Web.Security.MembershipUser user)
{
    byte[] userNameBytes = System.Text.Encoding.UTF32.GetBytes(user.UserName);
    byte[] emailBytes = System.Text.Encoding.UTF32.GetBytes(user.Email);
    byte[] createDateBytes = System.Text.Encoding.UTF32.GetBytes(user.CreationDate.ToString());

    int validationcode = 0;
    foreach (byte value in userNameBytes)   { validationcode += value; }
    foreach (byte value in emailBytes)      { validationcode += value; }
    foreach (byte value in createDateBytes) { validationcode += value; }

    validationcode -= (user.UserName.Length + user.Email.Length + user.CreationDate.ToString().Length);
    return validationcode.ToString(); 

}

Architecturally, all of the code related to this is in a single class called MailValidation. Everything related to the validation codes is done in that class, so moving from the overly-complex method to my simpler method was easy as pie. All I had to do was change the internal implementation. Now that I think of it, there's no reason why it can't be done using a provider model so that different implementations are plug-able.

Once the user is created, we generate the validation code. It is never stored on the server, but is sent to the user in an email. This email comes from the MailDefinition specified with the CreateUserWizard ... this little property points to a file that the wizard will automatically send to the new user. It will put the user name and password in there (with the proper formatting), but you'll need to trap the SendingMail event to modify it before it gets sent in order to put the URL and validation code in the email.

//This event fires when the control sends an email to the new user. 
protected void CreateUserWizard1_SendingMail(object sender, MailMessageEventArgs e)
{
    //Get the MembershipUser that we just created.
    MembershipUser newUser = Membership.GetUser(CreateUserWizard1.UserName);
    //Create the validation code
    string validationCode = MailValidation.CreateValidationCode(newUser);

    //And build the url for the validation page. 
    UriBuilder builder = new UriBuilder("http",
        Request.Url.DnsSafeHost,
        Request.Url.Port, Page.ResolveUrl("ValidateLogin.aspx"), "C=" + validationCode); 
    //Add the values to the mail message. 
    e.Message.Body = e.Message.Body.Replace("<%validationurl%>", builder.Uri.ToString());
    e.Message.Body = e.Message.Body.Replace("<%validationcode%>", validationCode);
    
}

One thing that I want to point out here ... I'm using the UriBuilder class to create the link back tot he validation page. Why don't I just take the full URL of the page and replace "CreateAccount.aspx" with the new page? Well, I would be concerned about canonicalization issue. I'm not saying that there would be any, but it's better to be safe. The UriBuilder will give us a good, clean url. The port is added in there so that it works even if it's running under the VS development web server, which puts the site on random ports. I do see a lot of developers using things like String.Replace() and parsing to get urls in these kinds of scenarios. I really wish they wouldn't.

Things do get a little more complicated, however, when actually validating the code. There is a separate form, of course, that does this. Basically, it collects the data from the user, regenerated the validation key and then compares them. It also checks the user's password by calling Membership.ValidateUser. If either of these fails, the user is not validated. Seems simple, right? Well, there is a monkey wrench in here. If the MembershipUser's IsValidated property is false, ValidateUser will always fail. So we can't fully validate the user until they are validated. But ... we need the password to validate their user account. See the problem? If I just check the validation code and the password is incorrect, you shouldn't be able to validate. What I had to wind up doing was this: once the validation code was validated, I had to then set IsApproved to true. Then I'd called ValidateUser. If this failed, I'd then set it back.

protected void Validate_Click(object sender, EventArgs e)
{
    //Get the membership user. 
    MembershipUser user = Membership.GetUser(UserName.Text);

    bool validatedUser = false;
    if (user != null)
    {
        if (MailValidation.CheckValidationCode(user, ValidationCode.Text))
        {
            //Have to set the user to approved to validate the password
            user.IsApproved = true;
            Membership.UpdateUser(user);
            if (Membership.ValidateUser(UserName.Text, Password.Text))
            {
                validatedUser = true;
            }
        }
    }
    //Set the validity for the user.
    SetUserValidity(user, validatedUser);
}

You do see, of course, where I had to Approve the user and then check. Not ideal, not what I wanted, but there was really no other way to to it. There are a couple of things, however, that I want to point out. Note that I do the actual, final work at the very end of the function. Nowhere am I called that SetUserValidity method until the end after I've explored all of code branches necessary. Again, I've seen developers embed this stuff directly in the If blocks. Ewww. And that makes it a lot harder if someone needs to alter the process later. Note that I also initialize the validatedUser variable to false. Assume the failure. Only when I know it's gone through all of the tests and is good do I set that validatedUser flag to true. It both helps keep the code simpler and ensure that if something was missed, it would fail.

Well, that's it for now. You can download the code at http://code.msdn.microsoft.com/jdotnet.



Tags: , ,

.NET Stuff | Security | Web (and ASP.NET) Stuff