Dealing with Profile Access in ASP.NET MVC Applications

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Introduction

Solution Explorer with SQL Express database

Accessing Profile Properties using ProfileBase Indexer

The most basic way of accessing profile properties is by using ProfileBase

class indexer. Have a look at the following piece of code:

[HttpPost]

public ActionResult CreateUser(CreateUserData data)

{

    MembershipCreateStatus status;

    Membership.CreateUser(data.UserID,data.Password,data.Email,data.Question,data.Answer,true, out status);



    if (status == MembershipCreateStatus.Success)

    {

        ProfileBase profile = ProfileBase.Create(data.UserID);

        profile["FirstName"] = data.FirstName;

        profile["LastName"] = data.LastName;

        profile.Save();

    }

    ....

    ....

}

The above code uses Create() method of ProfileBase class to get a

ProfileBase object for a specified user. It then uses indexer syntax to set

FirstName and LastName profile properties. Finally, Save() method is called

that persists the assigned values in the database.

The drawback of this method of accessing profile properties is that it

doesn’t provide strongly typed access to them. You must know the profile

properties defined in the web.config file. Any error in the profile property

names will result in an exception at run time (see below).

Any error in the profile property names will result in an exception at run time

Figure 3: Any error in the profile property names will result in an exception at run time

Accessing Profile Properties Using a Custom Profile Class

Now, let’s see how to bring back the strongly typed access to profile

properties in an ASP.NET MVC application. In this technique, you will create a

custom profile class that inherits from ProfileBase class. You will then add

property definitions to this class as per your requirement. Finally, you will

add a small configuration information so that ASP.NET is aware of your custom

class.

Begin by adding a new class in the Models folder and name it as Profile.

Next, code the Profile class as shown below:

public class Profile : ProfileBase

{

    public static Profile GetCurrent()

    {

        return (Profile)Create(Membership.GetUser().UserName);

    }

 

    public static Profile GetProfile(string userId)

    {

        return (Profile)Create(userId);

    }

 

    public string FirstName

    {

        get

        {

            return base["FirstName"] as string;

        }

        set

        {

            base["FirstName"] = value;

            Save();

        }

    }

 

    public string LastName

    {

        get

        {

            return base["LastName"] as string;

        }

        set

        {

            base["LastName"] = value;

            Save();

        }

    }

 

}

As you can see, the Profile class has two static methods – GetCurrent() and GetProfile().

The GetCurrent() method returns a Profile object for the currently logged in

user whereas GetProfile() method returns a Profile object for a specific user.

The Profile class also defines two public properties – FirstName and LastName.

The "set" property of both the profile properties calls Save() method

of ProfileBase base class so as to save the new property value immediately. If

you prefer to save them at one go rather than individually you can also call

Save() method in the calling code.

Now, open the web.config file again and modify the <profile> section

as shown below:

<profile enabled="true" defaultProvider="MyProfileProvider" inherits="AuthInMVC.Models.Profile">

As you can see, the <profile> element now has inherits attribute that

points to the fully qualified name of the custom profile class. This way

ASP.NET knows about your custom profile class. Also, comment out the

<properties> section you  added earlier. After making these changes

you can set profile properties in the code as follows:

Profile profile = Profile.GetProfile(data.UserID);

profile.FirstName = data.FirstName;

profile.LastName = data.LastName;

profile.Save();

In order to retrieve profile properties for a logged-in user you will write:

Profile profile = Profile.GetCurrent();

ViewBag.DisplayName = profile.FirstName + " " + profile.LastName; 

Accessing Profile Properties Using a DynamicObject

The third technique that can be used to access profile properties is using a

custom Dynamic Object. Normally when you wish to use some object in your code,

you first need to create a class and write properties and methods in it. You

can then create objects of that class, set their properties and invoke methods

on them. Using dynamic objects, however, you can add properties to an object

dynamically. One example of such a dynamic object can be found in ASP.NET MVC 3

itself. Consider the following piece of code written in a controller class:

ViewBag.StatusMessage = "Data saved successfully!";

ViewBag.StatusCode = "100";

ViewBag.LogDate = DateTime.Now;

ASP.NET MVC 3 provides a ViewBag object that allows you to store arbitrary

values that you wish to pass to the View. As illustrated in the above example,

you simply set properties on the ViewBag object as if they are coded in the

ViewBag object itself. In reality, ViewBag doesn’t contain any property

definitions for StatusMessage, StatusCode and LogDate (these names are

developer defined and you can use any valid name there). In other words, you

added properties dynamically to the ViewBag object.

The System.Dynamic namespaces provides DynamicObject class that can be used

to create your own custom dynamic object. In order to create your own dynamic

object using DynamicObject class you need to inherit it from DynamicObject and

override three methods, viz. TryGetMember, TrySetMember and TryInvokeMember.

The first two methods allow you to get and set dynamic properties whereas the

last method allows you to invoke method calls on the dynamic object. Let’s

create a DynamicProfile class that does just that. Add another class to Models

folder and name it as DynamicProfile. Key-in the following code in the

DynamicProfile class.

public class DynamicProfile : DynamicObject

{

    ProfileBase profile = null;

 

    public DynamicProfile()

    {

        profile = ProfileBase.Create(Membership.GetUser().UserName);

    }

 

    public DynamicProfile(string userId)

    {

        profile = ProfileBase.Create(userId);

    }

 

    public override bool TryGetMember(GetMemberBinder binder, out object result)

    {

        try

        {

            result = profile[binder.Name];

            return true;

        }

        catch

        {

            result = "Invalid Profile Property";

            return false;

        }

    }

 

    public override bool TrySetMember(SetMemberBinder binder, object value)

    {

        try

        {

            profile[binder.Name] = value;

            profile.Save();

            return true;

        }

        catch

        {

            return false;

        }

    }

 

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)

    {

        if (binder.Name == "Save")

        {

            profile.Save();

            result = null;

            return true;

        }

        else

        {

            throw new NotSupportedException("Only Save method is supported!");

        }

    }

}

The DynamicProfile class inherits from DynamicObject base class. There are

two overloads for the constructor. The first one instantiates a ProfileBase class

for currently logged in user whereas the second one instantiates a ProfileBase

class for a specific user. The TrySetMember() method sets a profile property

value by using ProfileBase indexer. On the same lines, TryGetMember() method

retrieves a profile property value using ProfileBase indexer. The

TryInvokeMember() method ensures that only Save() method can be called on the

DynamicProfile class and is intended to persist the profile property values.

Detailed discussion of creating dynamic objects is beyond the scope of this

article. See Using

DynamicObject and ExpandoObject for more details.

Once the DynamicProfile class is ready you can assign the profile properties

as shown below:

dynamic profile = new DynamicProfile(data.UserID);

profile.FirstName = data.FirstName;

profile.LastName = data.LastName;

profile.Save();

As you can see, the above code uses a dynamic keyword to create a dynamic

object. It then assigns the profile properties FirstName and LastName. To

retrieve the profile properties you will write:

dynamic profile = new DynamicProfile();

ViewBag.DisplayName = profile.FirstName + " " + profile.LastName;

Note that while using DynamicProfile, any errors in property names will

still generate runtime exceptions. However, the overall usage is simplified as

compared to using ProfileBase directly.

Summary

ASP.NET Website projects automatically generate ProfileCommon class so that

profile properties can be accessed in strongly typed fashion. This feature is

not available to ASP.NET MVC applications. However, with some efforts you can

achieve the same effect in MVC applications too. This article discussed three

ways of accessing profile properties in ASP.NET MVC applications. The first way

involves using ProfileBase indexer and is a primitive way of dealing with

profile properties. The second way is to create a custom class inheriting from

ProfileBase class and then adding property definitions to it. Using this second

approach you can access profile properties in a strongly typed way. The

downside, however, is that you need to create an extra class and ensure that

all profile properties have equivalent properties in the custom class. The

third approach is using a dynamic object. Though this approach is not exactly the

same as the second one, it does simplify coding. Depending on your need you can

go for any one of these approaches.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read