This article aims to explain how to work with
ProfileProvider in ASP.NET MVC 4, and implementing custom user profile.
As we know, the membership, roles and profile tables have
been restructured in MVC 4. Profile information of each user now gets stored in
“Profile” table in database.
The below screenshot is taken from an SQL Server database,
but you can easily correlate it with other database if your data provider is
Oracle, etc. Also, it will work if your profile table is pre-MVC 4 version
(i.e. aspnet_Profile).
Each row in this table represents a User profile associated
with a User (UserId links User with the profile).
For each user there is
only one row in this table containing complete information about profile.
PropertyNames >> Contains name of each property in
profile
PropertyValueStrings >> Text value of each property of
corresponding user’s profile. Its stored based on character index. Each profile
will have more than one property (as we will see later), and character indexing
helps in identifying values corresponding to property.
PropertyValueBinary >> Binary representation of
PropertyValueStrings field.
As such, we are least concerned about how the values are
stored and retrieved in database, because it’s a job of Profile provider in
ASP.NET MVC 4. We do not need to directly deal with this table at all!
Let us have a Walkthrough to understand how to implement
this:
If you are not aware about how to enable membership, role and profile providers (System.Web.Providers) in your MVC 4 application, please do visit this link before looking into below walkthrough.
STEP 1 Configure Profile provider in web.config:
Make sure you have following section in <system.web> in your
web.config file. Here, “DefaultConnection” is a ConnectionString's name in
<ConnectionStrings> section of your web.config.
Change name,
connectionStringName, and applicationName attributes according to your preferences.
<profile
defaultProvider="DefaultProfileProvider">
<providers>
<add
name="DefaultProfileProvider"
type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
connectionStringName="DefaultConnection"
applicationName="MyApp"/>
</providers>
</profile>
STEP 2 Define Profile properties:
Define properties that constitutes a user profile in your
application. Add them under above added <profiles> section in your
web.config. Profile properties can also be grouped, such as Contact, Address,
etc.
<properties>
<add
name="ForeNames" type="System.String"/>
<add name="LastName"
type="System.String"/>
<add name="Gender"
type="System.String"/>
<group name="Contact">
<add name="MobileNo"
type="System.String"/>
<add name="EmailAddress"
type="System.String"/>
</group>
</properties>
That’s all
you need to do in web.config.
STEP 3 Add
Model for Profile object in your MVC application:
This model
represents Profile in your MVC application. Ideally, it should be in sync with
the one defined in Web.config.
This model will
be used to pass Profile data from Controller action to View, and post them back
from View to Controller action.
Add
following model in “Models” folder in your MVC structure. (Make a new file, or
add it in existing file. It’s all up to you.)
public class ProfileModel
{
[Display(Name
= "First Name")]
public string
ForeNames { get; set;
}
[Display(Name = "Last
Name")]
public string
LastName { get; set;
}
[Display(Name = "Gender")]
public string Gender
{ get; set; }
[Display(Name = "Mobile
No")]
public string MobileNo
{ get; set; }
[Display(Name = "Email
Address")]
public string
EmailAddress { get; set;
}
}
STEP 4 Add
a new View, and Bind it with ProfileModel:
Add a new
view under “Views” folder (Place it under a controller-specific view folder, or
a “Shared” folder, wherever you wish to).
Bind the
view with the ProfileModel, and design UI accordingly, and also enforce
validations as you wish.
UI should
include entry fields for corresponding profile properties, as well as showing
validation messages, and a Submit button to the corresponding POST action in
controller. (Next steps will show you controller actions).
I am leaving
the designing of view to you!
Sample:
STEP 5 Write a GET action to fetch user
profile using Profile provider, and launch View created in above step:
A GET action
needs to be written in your controller to fetch profile information from
database using Profile provider.
public ActionResult
EditProfile()
{
ProfileBase _userProfile = ProfileBase.Create(HttpContext.User.Identity.Name);
ProfileModel _profile = new
ProfileModel();
if (_userProfile.LastUpdatedDate > DateTime.MinValue)
{
_profile.ForeNames = Convert.ToString(_userProfile.GetPropertyValue("ForeNames"));
_profile.LastName = Convert.ToString(_userProfile.GetPropertyValue("LastName"));
_profile.Gender = Convert.ToString(_userProfile.GetPropertyValue("Gender"));
_profile.MobileNo = Convert.ToString(_userProfile.GetProfileGroup("Contact").GetPropertyValue("MobileNo"));
_profile.EmailAddress = Convert.ToString(_userProfile.GetProfileGroup("Contact").GetPropertyValue("EmailAddress"));
}
return View(_profile);
}
The above
controller action is HTTP GET method, and should be called from “Edit Profile”
or similar link of your choice in your application. (I have given an example in STEP 7 later)
First of
all, it retrieves profile information of specific user (passed as parameter in
ProfileBase.Create method) from database.
Also, ProfileModel
is instantiated; this is what we are binding with the “Edit Profile” view.
Further, if
there exists a user profile for the user, then properties of ProfileModel instance
gets assigned according to the actual values in user profile.
Finally, a
View is invoked by supplying ProfileModel object for binding.
Note: Here, I assume that your View is
named as “EditProfile” and exists in the same controller.
If that’s
not the case, you need to set appropriate parameters in a call to “View”
method.
STEP 6 Write a POST action to post model to
View:
When a user clicks
on a Submit button in “Edit Profile” view, an HTTP Post action from a
controller gets called. This method accepts a ProfileModel instance updated by
user through “Edit Profile” view.
[HttpPost]
public ActionResult
EditProfile(ProfileModel model)
{
if
(ModelState.IsValid)
{
// Attempt to register the user profile
System.Web.Profile.ProfileBase
profile = System.Web.Profile.ProfileBase.Create(User.Identity.Name,
true);
if (profile != null)
{
profile.SetPropertyValue("Gender",
model.Gender);
profile.SetPropertyValue("ForeNames",
model.ForeNames);
profile.SetPropertyValue("LastName",
model.LastName);
profile.GetProfileGroup("Contact").SetPropertyValue("MobileNo", model.MobileNo);
profile.GetProfileGroup("Contact").SetPropertyValue("EmailAddress", model.EmailAddress);
profile.Save();
}
else
{
ModelState.AddModelError("",
"Error writing to Profile");
}
}
return View(model);
}
The above
controller action is an HTTP POST method, and gets called when a user clicks a
Submit button to Save profile changes.
It first
validates, if the user profile changes satisfies all the validations. If not,
it will create an instance of ProfileBase object using Reflector for the
specific user. It will assign profile properties from the values updated in
ProfileModel object. Once done, Save user profile in database. (If the profile
for the particular user does not exist, it will create a new one, or else, it
will update existing profile).
Step:7 Call to GET action
Finally, we
need a user interface to allow user to launch “Edit Profile” view. And for
that, we need to call “EditProfile” HTTP GET action (Step 5) of the controller
from some UI element.
@Html.ActionLink("Edit Profile", "EditProfile",
"Account")
Our example
is specific to deal with logged in user’s profile only. But you can easily
tweak it by adding a parameter to accept user name to allow users to view/ manage profile
of other users’ in your application.
Thank you, thank you so much !!!
ReplyDeleteI'm new to MVC and I was searching for some simple profile provider code for about 2 days now. I'm so glad that I found this article finally. It's so simple, and super clear, I love when I can just cut-paste code in my project and see it WORKING just fine. Everybody out there use some DBContext, that I couldn't implement for days. Hate when programmers complicate their code so much.
Thank you again for such a great article !!!
thanks Silvia for appreciating the efforts, and motivating words..
DeleteHopefully, I will be providing some more MVC posts in near future.
Keep Visiting :)
thanks
Thanks Nirman Doshi,
ReplyDeleteI really appricate your hard work and saving my time to get this done in minutes
-Thanks
Peter
Hi,Ikeep getting the following error.please advise.
ReplyDelete"The parameter 'usernameToMatch' must not be empty.
Parameter name: usernameToMatch"
in the following line of code
"if (_userProfile.LastUpdatedDate > DateTime.MinValue)"
Wonderful share Nirman, Thanks a lot for sharing !!
ReplyDeletethanks Sunny :)
Deletewow. great article
ReplyDeleteIt was really a nice post and I was really impressed by reading this .NET Online Course Bangalore
ReplyDeleteIf you want to take a great deal from this post then you
ReplyDeletehave to apply these strategies to your won blog.
keep up the good work. this is an Assam post. this to helpful, i have reading here all post. i am impressed. thank you. this is our digital marketing training center. This is an online certificate course
ReplyDeleteDot Net Training in Chennai | Dot Net Training in anna nagar | Dot Net Training in omr | Dot Net Training in porur | Dot Net Training in tambaram | Dot Net Training in velachery
the connection to the server localhost:8080 was refused - did you specify the right host or port?
ReplyDeleteaws vpc
aws inspector
azure traffic manager
azure-bastion
az 104 exam questions
ReplyDeletescrum master exam questions
dp 900 exam questions