Manage Custom User Properties at ASP.NET Identity 3 in MVC 5

1.5k views Asked by At

I'm currently practicing ASP.NET Identity 3.0 in MVC 5 - Followed a few tutorials and created a MVC project, I've managed the following so far:

  1. Added custom properties at Registration page
  2. Converted User ID from string to int
  3. Migrated and amended connection string to use SQL server
  4. Displayed custom properties at Manage Account page

Next I'd like to enable users to edit his/her own custom properties at the Manage Account page, but I'm so confused now - Can anyone please advise me how do I proceed from here?

UPDATE: By referring to Archil's examples provided below, I've updated my codes as shown below to manage custom properties:

ManageController.cs

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using IdentityMVC.Models;


namespace IdentityMVC.Controllers
{
    [Authorize]
    public class ManageController : Controller
    {

        ApplicationDbContext db = new ApplicationDbContext();

        private ApplicationSignInManager _signInManager;
        private ApplicationUserManager _userManager;

        public ManageController()
        {
        }

        public ManageController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
        {
            UserManager = userManager;
            SignInManager = signInManager;
        }

        public ApplicationSignInManager SignInManager
        {
            get
            {
                return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
            }
            private set 
            { 
                _signInManager = value; 
            }
        }

        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }

        //
        // GET: /Manage/Index
        public async Task<ActionResult> Index(ManageMessageId? message)
        {
            ViewBag.StatusMessage =
                message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
                : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
                : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set."
                : message == ManageMessageId.Error ? "An error has occurred."
                : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added."
                : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
                : "";

            var userId = User.Identity.GetUserId<int>();
            var user = UserManager.FindById(userId);
            var model = new IndexViewModel
            {
                HasPassword = HasPassword(),
                PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
                TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
                Logins = await UserManager.GetLoginsAsync(userId),
                Email = await UserManager.GetEmailAsync(userId),
                Surname = user.Surname,
                GivenName = user.GivenName,
                Honors = user.Honors,
                Address1 = user.Address1,
                Address2 = user.Address2,
                City = user.City,
                State = user.State,
                Postal = user.Postal,
                Country = user.Country,
                PSANo = user.PSANo,
                Id = user.Id,

            BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(User.Identity.GetUserId())
            };




            return View(model);
        }


        //
        // GET: /User/Edit/1
        public async Task<ActionResult> Edit()
        {
            var myUserId = User.Identity.GetUserId();
            int myUserIdint = Convert.ToInt32(myUserId);
            var myUser = db.Users.FirstOrDefault(x => x.Id == myUserIdint);

            if (myUserId == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var user = await UserManager.FindByIdAsync(myUserIdint);

            if (user == null)
            {
                return HttpNotFound();
            }

            var userRoles = await UserManager.GetRolesAsync(user.Id);


            return View(new EditUserViewModel()
            {
                Id = user.Id,
                Surname = user.Surname,
                GivenName = user.GivenName,
                Honors = user.Honors,
                Address1 = user.Address1,
                Address2 = user.Address2,
                City = user.City,
                State = user.State,
                Postal = user.Postal,
                Country = user.Country,
                PSANo = user.PSANo,

            });
        }

        //
        // POST: /User/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit([Bind(Include = "Surname,GivenName,Honors,Address1,Address2,City,State,Postal,Country,PSANo")] EditUserViewModel editUser)
        {

            if (ModelState.IsValid)
            {
                var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
                if (user == null)
                {
                   return HttpNotFound();
                }

                user.Surname = editUser.Surname;
                user.GivenName = editUser.GivenName;
                user.Honors = editUser.Honors;
                user.Address1 = editUser.Address1;
                user.Address2 = editUser.Address2;
                user.City = editUser.City;
                user.State = editUser.State;
                user.Postal = editUser.Postal;
                user.Country = editUser.Country;
                user.PSANo = editUser.PSANo;

                var userRoles = await UserManager.GetRolesAsync(user.Id);

                var result = await UserManager.AddToRolesAsync(user.Id);

                if (!result.Succeeded)
                {
                    ModelState.AddModelError("", result.Errors.First());
                    return View();
                }
                result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(userRoles).ToArray<string>());

                if (!result.Succeeded)
                {
                    ModelState.AddModelError("", result.Errors.First());
                    return View();
                }

                return RedirectToAction("Index");
            }
            ModelState.AddModelError("", "Something failed.");
            return View();
        }


        //
        // POST: /Manage/RemoveLogin
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> RemoveLogin(string loginProvider, string providerKey)
        {
            ManageMessageId? message;
            var result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId<int>(), new UserLoginInfo(loginProvider, providerKey));
            if (result.Succeeded)
            {

                var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
                if (user != null)
                {
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                }
                message = ManageMessageId.RemoveLoginSuccess;
            }
            else
            {
                message = ManageMessageId.Error;
            }
            return RedirectToAction("ManageLogins", new { Message = message });
        }

        //
        // GET: /Manage/AddPhoneNumber
        public ActionResult AddPhoneNumber()
        {
            return View();
        }


        //
        // GET: /Manage/ChangePassword
        public ActionResult ChangePassword()
        {
            return View();
        }

        //
        // POST: /Manage/ChangePassword
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ChangePassword(ChangePasswordViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId<int>(), model.OldPassword, model.NewPassword);
            if (result.Succeeded)
            {
                var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
                if (user != null)
                {
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                }
                return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
            }
            AddErrors(result);
            return View(model);
        }

        //
        // GET: /Manage/SetPassword
        public ActionResult SetPassword()
        {
            return View();
        }

        //
        // POST: /Manage/SetPassword
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> SetPassword(SetPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                var result = await UserManager.AddPasswordAsync(User.Identity.GetUserId<int>(), model.NewPassword);
                if (result.Succeeded)
                {
                    var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
                    if (user != null)
                    {
                        await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                    }
                    return RedirectToAction("Index", new { Message = ManageMessageId.SetPasswordSuccess });
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // GET: /Manage/ManageLogins
        public async Task<ActionResult> ManageLogins(ManageMessageId? message)
        {
            ViewBag.StatusMessage =
                message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
                : message == ManageMessageId.Error ? "An error has occurred."
                : "";
            var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
            if (user == null)
            {
                return View("Error");
            }
            var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId<int>());
            var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList();
            ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
            return View(new ManageLoginsViewModel
            {
                CurrentLogins = userLogins,
                OtherLogins = otherLogins
            });
        }

        //
        // POST: /Manage/LinkLogin
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult LinkLogin(string provider)
        {
            // Request a redirect to the external login provider to link a login for the current user
            return new AccountController.ChallengeResult(provider, Url.Action("LinkLoginCallback", "Manage"), User.Identity.GetUserId());
        }

        //
        // GET: /Manage/LinkLoginCallback
        public async Task<ActionResult> LinkLoginCallback()
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
            if (loginInfo == null)
            {
                return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
            }
            var result = await UserManager.AddLoginAsync(User.Identity.GetUserId<int>(), loginInfo.Login);
            return result.Succeeded ? RedirectToAction("ManageLogins") : RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && _userManager != null)
            {
                _userManager.Dispose();
                _userManager = null;
            }

            base.Dispose(disposing);
        }

#region Helpers
        // Used for XSRF protection when adding external logins
        private const string XsrfKey = "XsrfId";

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError("", error);
            }
        }

        private bool HasPassword()
        {
            var user = UserManager.FindById(User.Identity.GetUserId<int>());
            if (user != null)
            {
                return user.PasswordHash != null;
            }
            return false;
        }

        private bool HasPhoneNumber()
        {
            var user = UserManager.FindById(User.Identity.GetUserId<int>());
            if (user != null)
            {
                return user.PhoneNumber != null;
            }
            return false;
        }

        public enum ManageMessageId
        {
            AddPhoneSuccess,
            ChangePasswordSuccess,
            SetTwoFactorSuccess,
            SetPasswordSuccess,
            RemoveLoginSuccess,
            RemovePhoneSuccess,
            Error
        }

#endregion
    }
}

ManageViewModels.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;

namespace IdentityMVC.Models
{
    public class IndexViewModel
    {
        public bool HasPassword { get; set; }
        public IList<UserLoginInfo> Logins { get; set; }
        public string PhoneNumber { get; set; }
        public bool TwoFactor { get; set; }
        public bool BrowserRemembered { get; set; }
        public int Id { get; set; }
        public string Email { get; set; }
        public string Surname { get; set; }
        public string GivenName { get; set; }
        public string Honors { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Postal { get; set; }
        public string Country { get; set; }
        public string PSANo { get; set; }
    }

    public class EditUserViewModel
    {
        public int Id;

        [Required]
        [Display(Name = "Surname / Family Name*")]
        public string Surname { get; set; }

        [Required]
        [Display(Name = "Given Name")]
        public string GivenName { get; set; }

        [Display(Name = "Honors")]
        public string Honors { get; set; }

        [Required]
        [Display(Name = "Address Line 1")]
        public string Address1 { get; set; }

        [Display(Name = "Address Line 2")]
        public string Address2 { get; set; }

        [Required]
        [Display(Name = "City")]
        public string City { get; set; }

        [Required]
        [Display(Name = "State")]
        public string State { get; set; }

        [Required]
        [Display(Name = "Postal")]
        public string Postal { get; set; }

        [Required]
        [Display(Name = "Country")]
        public string Country { get; set; }

        [Display(Name = "PSA Membership No. (if applicable)")]
        public string PSANo { get; set; }


    }

    public class ManageLoginsViewModel
    {
        public IList<UserLoginInfo> CurrentLogins { get; set; }
        public IList<AuthenticationDescription> OtherLogins { get; set; }
    }

    public class FactorViewModel
    {
        public string Purpose { get; set; }
    }

    public class SetPasswordViewModel
    {
        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "New password")]
        public string NewPassword { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm new password")]
        [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }

    public class ChangePasswordViewModel
    {
        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "Current password")]
        public string OldPassword { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "New password")]
        public string NewPassword { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirm new password")]
        [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; }
    }

    public class AddPhoneNumberViewModel
    {
        [Required]
        [Phone]
        [Display(Name = "Phone Number")]
        public string Number { get; set; }
    }

    public class VerifyPhoneNumberViewModel
    {
        [Required]
        [Display(Name = "Code")]
        public string Code { get; set; }

        [Required]
        [Phone]
        [Display(Name = "Phone Number")]
        public string PhoneNumber { get; set; }
    }

    public class ConfigureTwoFactorViewModel
    {
        public string SelectedProvider { get; set; }
        public ICollection<System.Web.Mvc.SelectListItem> Providers { get; set; }
    }
}

View\Manage\Edit.cshtml

@model IdentityMVC.Models.EditUserViewModel
@{
    ViewBag.Title = "Edit";
}

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Edit My Profile</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.Surname, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Surname, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Surname, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.GivenName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.GivenName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.GivenName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Honors, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Honors, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Honors, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address1, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address1, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address1, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address2, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address2, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address2, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.City, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.State, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Postal, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Postal, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Postal, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Country, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Country, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Country, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.PSANo, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.PSANo, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.PSANo, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to Profile", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
1

There are 1 answers

4
Archil Labadze On BEST ANSWER

Good day, I've made it like this and it works for me: My Edit user model:

public class ManageEditUserViewModel
{
    public string Id { get; set; }

    [Required]
    [Display(Name = "FirstName")]
    public string FirstName { get; set; }
    [Required]
    [Display(Name = "LastName")]
    public string LastName { get; set; }

    public string DisplayName { get; set; }

    [Required(AllowEmptyStrings = false)]
    [Display(Name = "UserName")]
    public string UserName { get; set; }

    [Required(AllowEmptyStrings = false)]
    [Display(Name = "Email")]
    [EmailAddress]
    public string Email { get; set; }

    [Display(Name = "BirthDate")]
    [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime BirthDate { get; set; }
    [NotMapped]
    public int Day { get; set; }
    [NotMapped]
    public int Month { get; set; }
    [NotMapped]
    public int Year { get; set; }
    public int Gender { get; set; }
}

And here is my Controller (GET and Post):

//
    // GET: /User/Edit/1
    public async Task<ActionResult> Edit()
    {
        var myUserId = User.Identity.GetUserId();
        var myUser = db.Users.FirstOrDefault(x => x.Id == myUserId);

        if (myUserId == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        var user = await UserManager.FindByIdAsync(myUserId);

        if (user == null)
        {
            return HttpNotFound();
        }

        var userRoles = await UserManager.GetRolesAsync(user.Id);

        return View(new ManageEditUserViewModel()
        {
            Id = user.Id,
            UserName = user.UserName,
            Email = user.Email,
            FirstName = user.FirstName,
            LastName = user.LastName,
            DisplayName = user.FirstName + " " + user.LastName,
            Gender = user.Gender,
            BirthDate = user.BirthDate,
            Year = user.BirthDate.Year,
            Month = user.BirthDate.Month,
            Day = user.BirthDate.Day,

        });
    }

    //
    // POST: /User/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit([Bind(Include = "FirstName,LastName,DisplayName,Gender,UserName,Email,Id,Year,Month,Day")] ManageEditUserViewModel editUser)
    {
        DateTime dob = new DateTime(editUser.Year, editUser.Month, editUser.Day);
        if (ModelState.IsValid)
        {
            var user = await UserManager.FindByIdAsync(editUser.Id);
            if (user == null)
            {
                return HttpNotFound();
            }

            user.UserName = editUser.UserName;
            user.Email = editUser.Email;
            user.FirstName = editUser.FirstName;
            user.LastName = editUser.LastName;
            user.DisplayName = editUser.FirstName + "<span> </span>" + editUser.LastName;
            user.Gender = editUser.Gender;
            user.BirthDate = dob;

            var userRoles = await UserManager.GetRolesAsync(user.Id);

            var result = await UserManager.AddToRolesAsync(user.Id);

            if (!result.Succeeded)
            {
                ModelState.AddModelError("", result.Errors.First());
                return View();
            }
            result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(userRoles).ToArray<string>());

            if (!result.Succeeded)
            {
                ModelState.AddModelError("", result.Errors.First());
                return View();
            }

            var name = user.DisplayName;
            var message = editsuccess.Content;
            context.Clients.All.addNewMessageToPage(name, message);
            return RedirectToAction("MyProfile");
        }
        ModelState.AddModelError("", "Something failed.");
        return View();
    }

And finally view:

@model MyApp.Models.ManageEditUserViewModel
@{
ViewBag.Title = "EditUser";
 }
 <div class="page-header">
<h3 class="text-center text-uppercase">EditUser</h3>
</div>
<div class="row">
<div class="col-sm-3">
</div>
<div class="col-sm-6">
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">
            @Html.ValidationSummary(true)
            @Html.HiddenFor(model => model.Id)
            @Html.HiddenFor(model => model.UserName)
            @Html.HiddenFor(model => model.Email)

            <div class="form-group">
                @Html.LabelFor(model => model.FirstName, new { @class = "control-label col-md-2" })
                <div class="col-md-6">
                    @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.FirstName)
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" })
                <div class="col-md-6">
                    @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.LastName)
                </div>
            </div>


            <div class="form-group">
                <div class="col-lg-offset-2 col-md-6">
                    <strong>@Html.LabelFor(model => model.BirthDate) </strong>
                </div>
            </div>
            <div class="form-group">

                <div class="col-lg-offset-2 col-md-6">
                    @Html.DropDownListFor(model => model.Day, Enumerable.Range(1, 31).Select(i => new SelectListItem { Value = i.ToString(), Text = i.ToString() }), "Day")
                    @Html.DropDownListFor(model => model.Month, Enumerable.Range(1, 12).Select(i => new SelectListItem { Value = i.ToString(), Text = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i) }), "Month")
                    @Html.DropDownListFor(model => model.Year, Enumerable.Range(1900, 114).Select(i => new SelectListItem { Value = i.ToString(), Text = i.ToString() }), "Year")
                    @Html.ValidationMessageFor(model => model.BirthDate, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-lg-offset-2 col-md-6">
                    <label>
                        @Html.RadioButtonFor(x => x.Gender, 1) Male
                    </label>
                    <label>
                        @Html.RadioButtonFor(x => x.Gender, 2) Female
                    </label>
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-7">
                    <input type="submit" value="Save Changes" class="btn    btn-default" /> <span> </span> @Html.ActionLink("Back", "Index", null, new {      @class = "btn btn-default" })
                </div>
            </div>
        </div>
    }
 </div>
 <div class="col-sm-3">

 </div>
 </div>
 @section Scripts {
 @Scripts.Render("~/bundles/jqueryval")
 }

It's working fine you can also define your properties, home it will help you.