I'm working in MVC5/WebAPI using ASP.NET Identity, with a custom storage provider for my UserStore
, custom ApplicationUser
inheriting from IdentityUser
, and a pretty expansive configuration in the project (both MVC5 and WebAPI endpoints in the same project).
I've been working on the user management/settings controller (ManageController
), following the same principles the template projects use; however, with the additional fields I have in my ApplicationUser
, it is getting to the point that my view model is starting to be a duplicate of the ApplicationUser
class. I wanted someone to take a look at some of my code and let me know if they think the way I'm setting things up currently is appropriate, or if I am cluttering a view model with fields.
ManageViewModels.cs
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Microsoft.AspNet.Identity; using Microsoft.Owin.Security; using System.Security.Claims; namespace Disco.Models { public class IndexViewModel { public string Email { get; set; } 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 string FirstName { get; set; } public string LastName { get; set; } public string Picture { get; set; } public string Handle { 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; } } }
ApplicationUser.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Identity; using System.Security.Claims; using Newtonsoft.Json; namespace Schloss.AspNet.Identity.Neo4j { public class ApplicationUser : IdentityUser { public string FirstName { get; set; } public string LastName { get; set; } public DateTimeOffset DateOfBirth { get; set; } // @ handle / username public string Handle { get; set; } public string Picture { get; set; } public char Gender { get; set; } public string DeviceId { get; set; } // Most recently used mobile phone ID (iPhone, iPad, Android, etc) // Address public string City { get; set; } public string State { get; set; } public string ZIPCode { get; set; } public string County { get; set; } public string Country { get; set; } public string Address1 { get; set; } public string Address2 { get; set; } public string Address3 { get; set; } // SignalR public HashSet<string> ConnectionIds { get; set; } // SignalR connections set (for handling multiple live sessions, propagation of push notifications) //public static string Labels { get { return "User"; } } // Helper Properties [JsonIgnore] public String FullName { get { return (FirstName + " " + LastName).Trim(); } // helper property to format user's full name } public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) { // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); // Add custom user claims here return userIdentity; } public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType) { // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType var userIdentity = await manager.CreateIdentityAsync(this, authenticationType); // Add custom user claims here return userIdentity; } } }
ManageController.cs (just the Index view)
// // 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(); var user = await UserManager.FindByIdAsync(userId); var model = new IndexViewModel { Email = await UserManager.GetEmailAsync(userId), HasPassword = await UserManager.HasPasswordAsync(userId), PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), Logins = await UserManager.GetLoginsAsync(userId), BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId), FirstName = user.FirstName, LastName = user.LastName, Picture = user.Picture, Handle = user.Handle }; return View(model); }