Sunday, July 21, 2013

Programatically accessing your custom fields in VS2012 SimpleMembership

(This is the 3rd of a 3-article series, on using SimpleMembership along with customized fields)

Article 1: Visual Studio 2012 uses SimpleMembership as its new Membership Provider
Article 2: Adding custom fields to a VS2012 MVC4 SimpleMembership system
Article 3: This article.

In the previous article, I covered how to create custom Membership fields, such as a registered user's name or phone number. This article explains how to use these added fields programatically from within your project.

The key steps that we'll follow can be summarized as:

  1. Define the additional fields in the UserProfile class, so we can access them programatically (and get IntelliSense for them as well);
  2. Add them to the RegisterModel class, and various other places per details in the above article, so user's can supply values into them when registering;
  3. Run the program and go to the "Register" page (but do not create a new user yet. This will create the database tables (if they're not present);
  4. Modify the UserProfile table and add the required fields, such as FirstName and LastName;
  5. Tweak some code in the system-generated InitializeSimpleMembershipAttribute.cs program, to avoid an exception when the system makes a duplicate call to InitializeDatabaseConnection();
  6. Add code to the Index action method in the Home controller, to actually use the new fields we have added.
  7. Run the program, create a new user and supply data into the new fields, and test out everything.
Out of the above, steps 1 thru 4 are already covered in the article previously referenced. Please follow all the steps in that article, to make sure we've got the base correctly set up! So let us start from step-5.

NOTE: The above article only defined a single additional column - FullName. But here, we're using 2 additional columns - FirstName and LastName (in order to illustrate the use of multiple columns). In your own code you can, of course, create whatever columns you need to use, just making sure that they're consistent across the board.

(HEADS-UP: I have called my test project "SimpleMembershipCustomFields", so you'll see that namespace reference in the code given below. You'll need to replace that with your own project namespace reference.)

Tweak some code in the system-generated InitializeSimpleMembershipAttribute.cs program

The Websecurity method call already exists in the program. Enclose that code in an if() condition, else it sometimes gets called multiple times when doing various Membership-related tasks resulting an exception:

    if (!WebSecurity.Initialized)
            WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

Add code to the Index action method in the Home controller, to actually use the new fields

For demo purposes, I've simply added a text string derived from the newly added fields (FirstName and LastName).

First, in the "using" section, add the following namespace references:
// Customization: References to the additional field(s)
using WebMatrix.WebData;
using SimpleMembershipCustomFields.Models;
(substituting your own project's namespace reference instead of "SimpleMembershipCustomFields")

Next, add code in the Index action method to use the new fields. For your ready reference, I've simply copied over the entire Index() method. The code I've added here is all inside the IsAuthenticated condition; the rest is just the default generated program:

public ActionResult Index()
    ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

    if (WebSecurity.IsAuthenticated)
        // The call to InitializeDatabaseConnection is mandatory before calling
        // any other WebSecurity method (test it by commenting it out)
        if (!WebSecurity.Initialized)
                "DefaultConnection", "UserProfile", "UserId", "UserName", 
                autoCreateTables: false);

        UsersContext uc = new UsersContext();
        UserProfile userProfile = uc.UserProfiles.Where(x => x.UserId == WebSecurity.CurrentUserId).FirstOrDefault();

        ViewBag.Message = "Hello, " + userProfile.FirstName + 
            "! Your last name is: " + userProfile.LastName + ". " +
            "Welcome, " + userProfile.FirstName + " " + userProfile.LastName + "!";

    return View();

Something to note here is that we're (conditionally) calling the InitializeDatabaseConnection() method, although the last parameter is "false" (it was "true" in the call from InitializeSimpleMembershipAttribute.cs). If you're going to need this call from multiple places in your project, it may make sense to extract it out into its own separate method, with "autoCreateTables" as a param.

Run the program, and test out everything.

If all is well, you should be able to create a new user and supply values into the new fields, using the Register screen. The resulting Index page should look similar to the screenshot below. I've also added screenshots for the signed-out homepage as well as the database table contents.

Thanks for reading! Happy coding!

(This is the 3rd of a 3-article series, on using SimpleMembership along with customized fields)

Article 1: Visual Studio 2012 uses SimpleMembership as its new Membership Provider
Article 2: Adding custom fields to a VS2012 MVC4 SimpleMembership system
Article 3: This article.

Wednesday, July 10, 2013

Avoid pausing Bootstrap Carousel on mouse hover

For one of my projects, I'm using Twitter Bootstrap (ver 2.3.2) as the CSS framework, along with FontAwesome font-based icons. What a great toolset! Highly recommended.

The Bootstrap "Carousel" JavaScript control is a very nice implementation. However, it has 2 default settings which I wanted to override and substitute with my own preferences:

  1. By default it pauses when the mouse is hovering over the control. This caused a problem because as soon as the user goes to the site, if by chance they move the mouse and bring it over the carousel, it stops cycling and leaves the user thinking that they need to click the buttons to make it move.
  2. Also, without the mouse hovering over it, the carousel keeps auto-transitioning endlessly. This is quite needless and in fact counterproductive, as it becomes a distraction to the reader and stops them from focusing on the rest of the page content.

To solve these, I wanted to:

  1. Keep the carousel cycling even on mouse-over (users can always come back to a particular slide by clicking the navigation buttons in the carousel);
  2. Stop auto-transitioning after the last slide has rendered.

Here's the JavaScript that needs to be added to the end of the page, in order to accomplish the tasks:

    <script type="text/javascript">
        @*Start up the carousel, and override the default mouseover pause*@
            interval: 5000,
            pause: 'none'

        @*Stop auto-transition after the last slide*@
        $('#myCarousel').on('slid', '', function () {
            if ($('.carousel-inner .item:last').hasClass('active')) {

The "interval: 5000" specifies that the slides should transition after 5 seconds, and also ensures that they actually in fact *do* start transitioning upon page load. Without that code, sometimes the transition doesn't start until the user clicks on the "next slide" navigation, which would be another irritant.

(The above code is using the MVC Razor syntax of having comments enclosed inside @*comment text*@)

Twitter Bootstrap is a great tool, and a big time saver as a CSS framework for any new website development project.

Happy web coding, and building great user experiences!