Manage Custom User Properties at ASP.NET Identity 3 in MVC 5 - asp.net-mvc-5

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:
Added custom properties at Registration page
Converted User ID from string to int
Migrated and amended connection string to use SQL server
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")
}

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.

Related

Save a Value outside of Dropdownlist EF6

I wish to save an id field called AssetAssignmentID the value of "2" everytime a new modelname is saved.
I was looking to see if i could do the following;
That was if the Modelname was not null, then save both the ModelName and AssetAssignmentID to = "2"
public ActionResult Create(ClinicalAsset clinicalAssets)
{
try
{
if (ModelState.IsValid)
{
if (clinicalAssets.ModelName != null)
{
clinicalAssets.ModelName = clinicalAssets.ModelName;
clinicalAssets.AssetAssignmentID = "2";
}
db.ClinicalAssets.Add(clinicalAssets);
db.SaveChanges();
return RedirectToAction("Details", "ClinicalAssets", new { ClinicalAssetID = clinicalAssets.ClinicalAssetID });
}
}
However it complains that an object reference is required for non-static field.
If I make reference to the AssetAssignmentID in the ClinicalAsset Model I cannot convert type int to Model.
The populated dropdownlist
private void PopulateModelDropDownList(object selectedModel = null)
{
var ModelsQuery = from d in db.Models.Where(x => x.AssetAssignmentID == 2) orderby d.ModelName select d;
ViewBag.ModelDropDown = new SelectList(ModelsQuery, "ModelID", "ModelName", selectedModel);
}
I would expect that every time a new ModelName is submitted to the database the AssetAssignmentID would always equal the value of two.
edit
I have also tried
var clinicalAsset = new ClinicalAsset { AssetAssignmentID = 2 };
if (clinicalAssets.ModelName != null)
{
clinicalAssets.ModelName = clinicalAssets.ModelName;
}
db.ClinicalAssets.Add(clinicalAsset);
db.SaveChanges();
return RedirectToAction("Details", "ClinicalAssets", new { ClinicalAssetID = clinicalAssets.ClinicalAssetID });
but the error is: Cannot implicitly convert type 'int' to 'Assets.Models.Model'
ClinicalAsset Model:
using Assets.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Assets.Areas.Clinical.Models
{
public class ClinicalAsset
{
[Key]
public int ClinicalAssetID { get; set; }
public int AssetTypeID { get; set; }
public int? ProductID { get; set; }
public int? ManufacturerID { get; set; }
public int? ModelID{ get; set; }
public int? SupplierID { get; set; }
[StringLength(100, MinimumLength = 2)]
public string SerialNo { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yy}", ApplyFormatInEditMode = true)]
public DateTime? PurchaseDate { get; set; }
[StringLength(100, MinimumLength = 2)]
public string PoNo { get; set; }
[DisplayFormat(DataFormatString = "{0:c2}", ApplyFormatInEditMode = true)]
public decimal? Costing { get; set; }
public int? TeamID { get; set; }
public int? BudgetCodeID { get; set; }
public int? StaffID { get; set; }
public bool? Filter { get; set; }
public virtual Model ModelName { get; set; }
public virtual Model AssetAssignmentID { get; set; }
public virtual BudgetCode BudgetCodeJoinColumn { get; set; }
public virtual Product ProductName { get; set; }
public virtual AssetType AssetTypeName { get; set; }
public virtual Manufacturer ManufacturerName { get; set; }
public virtual Staff StaffName { get; set; }
public virtual Team TeamName { get; set; }
public virtual Supplier SupplierName { get; set; }
public virtual ICollection<ClinicalPAT> ClinicalPATs { get; set; }
}
}
Models model
namespace Assets.Models
{
public class Model
{
[Key]
public int ModelID { get; set; }
public int AssetAssignmentID { get; set; }
public string ModelName { get; set; }
}
}
Create Form:
#model Assets.Areas.Clinical.Models.ClinicalAsset
<link href="~/Content/bootstrap-timepicker.min.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Create Asset";
ViewBag.Current = "Create Asset";
}
<div class="pageheader">
<h2><i class="fa fa-pencil"></i>Add Clinical Assets</h2>
<div class="breadcrumb-wrapper">
<span class="label">You are here:</span>
<ol class="breadcrumb">
<li>Asset Management System</li>
<li class="active">Clinical Assets / Add Asset</li>
</ol>
</div>
</div>
<div class="contentpanel">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-btns">
−
</div>
<h4 class="panel-title">Create an asset.</h4>
<p>Please fill in the required boxes as a minimum.<text style="color:red;"> * </text> </p>
</div>
#Html.ValidationSummary()
<div class="panel-body">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.AssetTypeID, "Asset Type:", new { #class = "control-label" })
#Html.DropDownListFor(model => model.AssetTypeID, (SelectList)ViewBag.AssetTypeDropDown, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.AssetTypeID, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
<div class="col-sm-6">
<div class="form-group">
<label id="lbltipAddProduct">Select Product:</label> <label id="lbltipAddProduct2" style="display:none;">Enter Product:</label>
<label id="hideproductbutton" style="float: right;"><i class="myClass fa fa-edit" id="product"></i></label>
<label id="shownewproductbutton" Style="float: right; display:none;"><i class="glyphicon glyphicon-remove-circle" id="product2"></i></label>
<div id="Product">
#Html.DropDownListFor(model => model.ProductID, (SelectList)ViewBag.ProductDropDown, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ProductID, "", new { #class = "text-danger" })
</div>
<div class="js-product" style="display:none;">
#Html.EditorFor(model => model.ProductName.ProductName, new { htmlAttributes = new { #class = "form-control", #placeholder = "Enter Product Name Here", disabled = "disabled" } })
#Html.ValidationMessageFor(model => model.ProductName.ProductName, "", new { #class = "text-danger" })
</div>
</div>
</div><!-- col-sm-6 -->
</div><!-- row -->
<div id="inputs-for-filters1">
<div class="form-group">
#Html.EditorFor(model => model.Filter)
#Html.LabelFor(model => model.Filter, "Filter Required?")
#Html.ValidationMessageFor(model => model.Filter)
</div>
</div>
<div id="inputs-for-filters2">
<div class="form-group">
#Html.EditorFor(model => model.Filter)
#Html.LabelFor(model => model.Filter, "Filter Required?")
#Html.ValidationMessageFor(model => model.Filter)
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label id="lbltipAddManufacturer">Select Manufacturer:</label> <label id="lbltipAddManufacturer2" style="display:none;">Enter Manufacturer:</label>
<label id="hidemanufacturerbutton" style="float: right;"><i class="myClass fa fa-edit" id="manufacturer"></i></label>
<label id="shownewmanufacturerbutton" Style="float: right; display:none;"><i class="glyphicon glyphicon-remove-circle" id="manufacturer2"></i></label>
<div id="Manufacturer">
#Html.DropDownListFor(model => model.ManufacturerID, (SelectList)ViewBag.ManufacturerDropDown, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ManufacturerID, "", new { #class = "text-danger" })
</div>
<div class="js-manufacturer" style="display:none;">
#Html.EditorFor(model => model.ManufacturerName.ManufacturerName, new { htmlAttributes = new { #class = "form-control", #placeholder = "Enter Name Here", disabled = "disabled" } })
#Html.ValidationMessageFor(model => model.ManufacturerName.ManufacturerName, "", new { #class = "text-danger" })
</div>
</div>
</div><!-- col-sm-6 -->
<div class="col-sm-6">
<div class="form-group">
<label id="lbltipAddModel">Select Model:</label> <label id="lbltipAddModel2" style="display:none;">Enter Model Type:</label>
<label id="hidemodelbutton" style="float: right;"><i class="myClass fa fa-edit" id="model"></i></label>
<label id="shownewmodelbutton" Style="float: right; display:none;"><i class="glyphicon glyphicon-remove-circle" id="model2"></i></label>
<div id="Model">
#Html.DropDownListFor(model => model.ModelID, (SelectList)ViewBag.ModelDropDown, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ModelID, "", new { #class = "text-danger" })
</div>
<div class="js-model" style="display:none;">
#Html.EditorFor(model => model.ModelName.ModelName, new { htmlAttributes = new { #class = "form-control", #placeholder = "Enter Name Here", disabled = "disabled" } })
#Html.ValidationMessageFor(model => model.ModelName.ModelName, "", new { #class = "text-danger" })
</div>
</div>
</div><!-- col-sm-6 -->
</div><!-- row -->
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label id="lbltipAddSupplier">Select Supplier:</label> <label id="lbltipAddSupplier2" style="display:none;">Enter Supplier:</label>
<label id="hidesupplierbutton" style="float: right;"><i class="myClass fa fa-edit" id="supplier"></i></label>
<label id="shownewsupplierbutton" Style="float: right; display:none;"><i class="glyphicon glyphicon-remove-circle" id="supplier2"></i></label>
<div id="Supplier">
#Html.DropDownListFor(model => model.SupplierID, (SelectList)ViewBag.SupplierDropDown, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.SupplierID, "", new { #class = "text-danger" })
</div>
<div class="js-supplier" style="display:none;">
#Html.EditorFor(model => model.SupplierName.SupplierName, new { htmlAttributes = new { #class = "form-control", #placeholder = "Enter Supplier Name Here", disabled = "disabled" } })
#Html.ValidationMessageFor(model => model.SupplierName.SupplierName, "", new { #class = "text-danger" })
</div>
</div>
</div><!-- col-sm-6 -->
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.SerialNo, "Serial No:", new { #class = "control-label" })
#Html.EditorFor(model => model.SerialNo, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SerialNo, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
</div><!-- row -->
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.PurchaseDate, "Purchase Date:", new { #class = "control-label" })
#Html.TextBoxFor(m => m.PurchaseDate, new { #class = "form-control datepicker", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.PurchaseDate, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.PoNo, "Purchase OrderNo:", new { #class = "control-label" })
#Html.EditorFor(model => model.PoNo, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PoNo, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
</div><!-- row -->
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.BudgetCodeID, "Budget Code:", new { #class = "control-label" })
#Html.DropDownListFor(m => m.BudgetCodeID, (SelectList)ViewBag.BudgetsList, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BudgetCodeID, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.Costing, "Cost:", new { #class = "control-label" })
#Html.EditorFor(model => model.Costing, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Costing, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
</div><!-- row -->
<div class="row">
<div class="col-sm-6">
<div class="form-group">
#Html.LabelFor(model => model.TeamID, "Team:", new { #class = "control-label" })
#Html.DropDownListFor(model => model.TeamID, ViewBag.TeamList as SelectList, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TeamID, "", new { #class = "text-danger" })
</div>
</div><!-- col-sm-6 -->
<div class="col-sm-6">
<div class="form-group">
<label id="lbltipAddStaff">Select Staff Member:</label> <label id="lbltipAddStaff2" style="display:none;">Enter Staff Member Name:</label>
<label id="hidestaffbutton" Style="float: right;"><i class="myClass fa fa-edit" id="staff"></i></label>
<label id="shownewstaffbutton" Style="float: right; display:none;"><i class="glyphicon glyphicon-remove-circle" id="staff2"></i></label>
<div id="Staff">
#Html.DropDownListFor(model => model.StaffID, (SelectList)ViewBag.StaffDropDown, "Please Select From The List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.StaffID, "", new { #class = "text-danger" })
</div>
<div class="js-staff" style="display:none;">
#Html.EditorFor(model => model.StaffName.StaffName, new { htmlAttributes = new { #class = "form-control", #placeholder = "Enter Name Here", disabled = "disabled" } })
#Html.ValidationMessageFor(model => model.StaffName.StaffName, "", new { #class = "text-danger" })
</div>
</div>
</div><!-- col-sm-6 -->
</div><!-- row -->
</div><!-- panel-body -->
<div class="panel-footer">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</div>
</div>
}
</div><!-- panel -->
#section Scripts {
<script src="~/Scripts/jquery-ui-1.10.3.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
#Scripts.Render("~/bundles/jqueryval")
<script>
// Date Picker
jQuery('#PurchaseDate').datepicker({ dateFormat: 'dd/mm/yy' });
jQuery('#WarrantyEndDate').datepicker({ dateFormat: 'dd/mm/yy' });
jQuery('#InspectionDate').datepicker({ dateFormat: 'dd/mm/yy' });
jQuery('#InspectionDueDate').datepicker({ dateFormat: 'dd/mm/yy' });
jQuery('#datepicker-inline').datepicker();
jQuery('#datepicker-multiple').datepicker({
numberOfMonths: 3,
showButtonPanel: true
});
$(document).ready(function () {
$("#inputs-for-filters1").hide();
$("#inputs-for-filters2").hide();
$("#AssetTypeID").change(function () {
if ($("#AssetTypeID").val() == "3") {
$("#inputs-for-filters1").show();
}
else {
$("#inputs-for-filters1").hide();
}
});
$("#ProductID").change(function () {
if ($("#ProductID").val() == "24") {
$("#inputs-for-filters2").show();
}
else {
$("#inputs-for-filters2").hide();
}
});
});
$(document).ready(function () {
$("#staff").click(function () {
$("#Staff").toggle();
$(".js-staff").toggle();
$('#lbltipAddStaff').toggle();
$('#lbltipAddStaff2').toggle();
$(".js-staff input[type='text']").attr("disabled", false);
$("#hidestaffbutton").toggle();
$("#shownewstaffbutton").toggle();
});
});
$(document).ready(function () {
$("#staff2").click(function () {
$("#Staff").toggle();
$(".js-staff").toggle();
$('#lbltipAddStaff').toggle();
$('#lbltipAddStaff2').toggle();
$(".js-staff input[type='text']").attr("disabled", true);
$("#hidestaffbutton").toggle();
$("#shownewstaffbutton").toggle();
});
});
$(document).ready(function () {
$("#model").click(function () {
$("#Model").toggle();
$(".js-model").toggle();
$('#lbltipAddModel').toggle();
$('#lbltipAddModel2').toggle();
$(".js-model input[type='text']").attr("disabled", false);
$("#hidemodelbutton").toggle();
$("#shownewmodelbutton").toggle();
});
});
$(document).ready(function () {
$("#model2").click(function () {
$("#Model").toggle();
$(".js-model").toggle();
$('#lbltipAddModel').toggle();
$('#lbltipAddModel2').toggle();
$(".js-model input[type='text']").attr("disabled", true);
$("#hidemodelbutton").toggle();
$("#shownewmodelbutton").toggle();
});
});
$(document).ready(function () {
$("#manufacturer").click(function () {
$("#Manufacturer").toggle();
$(".js-manufacturer").toggle();
$('#lbltipAddManufacturer').toggle();
$('#lbltipAddManufacturer2').toggle();
$(".js-manufacturer input[type='text']").attr("disabled", false);
$("#hidemanufacturerbutton").toggle();
$("#shownewmanufacturerbutton").toggle();
});
});
$(document).ready(function () {
$("#manufacturer2").click(function () {
$("#Manufacturer").toggle();
$(".js-manufacturer").toggle();
$('#lbltipAddManufacturer').toggle();
$('#lbltipAddManufacturer2').toggle();
$(".js-manufacturer input[type='text']").attr("disabled", true);
$("#hidemanufacturerbutton").toggle();
$("#shownewmanufacturerbutton").toggle();
});
});
$(document).ready(function () {
$("#product").click(function () {
$("#Product").toggle();
$(".js-product").toggle();
$('#lbltipAddProduct').toggle();
$('#lbltipAddProduct2').toggle();
$(".js-product input[type='text']").attr("disabled", false);
$("#hideproductbutton").toggle();
$("#shownewproductbutton").toggle();
});
});
$(document).ready(function () {
$("#product2").click(function () {
$("#Product").toggle();
$(".js-product").toggle();
$('#lbltipAddProduct').toggle();
$('#lbltipAddProduct2').toggle();
$(".js-product input[type='text']").attr("disabled", true);
$("#hideproductbutton").toggle();
$("#shownewproductbutton").toggle();
});
});
$(document).ready(function () {
$("#supplier").click(function () {
$("#Supplier").toggle();
$(".js-supplier").toggle();
$('#lbltipAddSupplier').toggle();
$('#lbltipAddSupplier2').toggle();
$(".js-supplier input[type='text']").attr("disabled", false);
$("#hidesupplierbutton").toggle();
$("#shownewsupplierbutton").toggle();
});
});
$(document).ready(function () {
$("#supplier2").click(function () {
$("#Supplier").toggle();
$(".js-supplier").toggle();
$('#lbltipAddSupplier').toggle();
$('#lbltipAddSupplier2').toggle();
$(".js-supplier input[type='text']").attr("disabled", true);
$("#hidesupplierbutton").toggle();
$("#shownewsupplierbutton").toggle();
});
});
</script>
}
UPDATE
I now have the AssignmentID saving as 2, but it creates a new entry in the database rather than assigning two values to the same field
Thanks to A.Nadjar & Train
Although i didn't need a Viewmodel the solution was to save the data with THE 1 TO MANY relationship saving first, followed by the main entity last, and also ensure the foreign key was created for the AssetAssignmentID in the model.
Code:
if (ModelState.IsValid)
{
var newClinicalAsset = new ClinicalAsset();
var NewModel = new Model();
if (clinicalAssetVM.AssetTypeID == 0)
{
}
else
{
newClinicalAsset.AssetTypeID = clinicalAssetVM.AssetTypeID;
}
if (clinicalAssetVM.ModelName != null)
{
NewModel.ModelAssetAssignmentID = clinicalAssetVM.AssetAssignmentID.AssetAssignmentID;
NewModel.ModelName = clinicalAssetVM.ModelName.ModelName;
db.Models.Add(NewModel);
db.SaveChanges();
}
newClinicalAsset = new ClinicalAsset { ModelID = NewModel.ModelID, AssetTypeID = newClinicalAsset.AssetTypeID};
db.ClinicalAssets.Add(newClinicalAsset);
db.SaveChanges();
return RedirectToAction("Details", "ClinicalAssets", new { ClinicalAssetID = clinicalAssetVM.ClinicalAssetID });
}

My Validation attribute with client side

I have a business rule of my page - controls with date should be in ascending order. I.e. entered value to Date1 < entered value to Date2 < Date3
My attribute:
public class CompareDateAttribute : ValidationAttribute, IClientValidatable
{
public CompareDateAttribute(string datesString)
{
_datesString = datesString;
}
private string _datesString;
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
//ErrorMessage = this.FormatErrorMessage(metadata.DisplayName),
ErrorMessage = String.Format("Invalid date {0}", metadata.PropertyName),
ValidationType = "datecomparer"
};
rule.ValidationParameters.Add("dates", _datesString);
yield return rule;
}
}
client side:
$.validator.addMethod("datecomparer", function (value, element, param) {
//var valid = true;
var arrElements = param.split(',');
var datePreviousStr = null;
$.each(arrElements, function (index, v) {
if (datePreviousStr == null)
{
datePreviousStr = $('#' + v).val();
}
else
{
var dateCurrentStr = $('#' + v).val();
if (dateCurrentStr == '')
{
return false;
}
var dateCurrent = $.datepicker.parseDate("mm/dd/yy", dateCurrentStr);
var datePrevious = $.datepicker.parseDate("mm/dd/yy", datePreviousStr);
if (dateCurrent < datePrevious)
{
return false;
}
else
{
datePreviousStr = dateCurrentStr;
}
}
});
return true;
});
$.validator.unobtrusive.adapters.addSingleVal("datecomparer", "dates");
Model:
public class Valid6
{
[CompareDate("Date1,Date2,Date3")]
public DateTime Date1 { get; set; }
[CompareDate("Date1,Date2,Date3")]
public DateTime Date2 { get; set; }
[CompareDate("Date1,Date2,Date3")]
public DateTime Date3 { get; set; }
}
and view (necessary part):
<div class="form-horizontal">
<h4>Valid6</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Date1, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date1, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date1, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Date2, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date2, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date2, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Date3, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date3, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date3, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
also, part of result HTML:
<input class="form-control text-box single-line valid" data-val="true" data-val-date="The field Date3 must be a date." data-val-datecomparer="Invalid date Date3" data-val-datecomparer-dates="Date1,Date2,Date3" data-val-required="The Date3 field is required." id="Date3" name="Date3" type="datetime" value="">
but when I enter Date1='11/11/2010' and Date2='11/11/2009' debugger says, that datecomparer method returns false, but validator message is not appeared.
Why and how to solve?
Found the solution - "return false;" inside loop returns only from loop and then find "return true" on the end of method.
should be like :
$.validator.addMethod("datecomparer", function (value, element, param) {
var valid = true;
var arrElements = param.split(',');
var datePreviousStr = null;
$.each(arrElements, function (index, v) {
if (datePreviousStr == null)
{
datePreviousStr = $('#' + v).val();
}
else
{
var dateCurrentStr = $('#' + v).val();
if (dateCurrentStr == '')
{
valid = false;
return;
}
var dateCurrent = $.datepicker.parseDate("mm/dd/yy", dateCurrentStr);
var datePrevious = $.datepicker.parseDate("mm/dd/yy", datePreviousStr);
if (dateCurrent < datePrevious)
{
valid = false;
return;
}
else
{
datePreviousStr = dateCurrentStr;
}
}
});
return valid;
});
$.validator.unobtrusive.adapters.addSingleVal("datecomparer", "dates");

error on partial view data are not pasted to the model

Good day. I really do not know which part will I fix.
This is the view model
public class EmployeeViewModel
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public virtual ICollection<FacultySchedViewModel> FacultyScheduleViewModels { get; set; }
}
public class FacultySchedViewModel
{
public int ID { get; set; }
public int EmployeeID { get; set; }
public string Schedule { get; set; }
public string Room { get; set; }
}
the main view- in here i will just hide or show it because it is optional.
#Html.Partial("_Create", new LeavesAndTrainings.ViewModels.FacultySchedViewModel())
and in the main view the javascript to dynamically create a textboxes in the partial view
<script>
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var colCount = table.rows[0].cells.length;
for (var i = 0; i < colCount; i++) {
var newcell = row.insertCell(i);
newcell.innerHTML = table.rows[0].cells[i].innerHTML;
switch (newcell.childNodes[0].type) {
case "text":
newcell.childNodes[0].value = "";
break;
case "checkbox":
newcell.childNodes[0].checked = false;
break;
case "select":
newcell.childNodes[0].selectedIndex = 0;
clear_attrib();
break;
}
}
}
function deleteRow(tableID) {
try {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
for (var i = 0; i < rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if (null != chkbox && true == chkbox.checked) {
if (rowCount <= 1) {
alert("Cannot delete all the rows.");
break;
}
table.deleteRow(i);
rowCount--;
i--;
}
}
} catch (e) {
alert(e);
}
}
this is the partial view - used BeginCollectionItem to dynamically create an index on the textboxes
<table class="table" id="AddSchedule">
#using (Html.BeginCollectionItem("FacultySchedViewModel"))
{
<tr>
<td><input type="checkbox" name="chk[]" class="checkbox_style" /></td>
<td>
#Html.HiddenFor(model => model.ID, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(model => model.Schedule, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Schedule, "", new { #class = "text-danger" })
</td>
<td>
#Html.EditorFor(model => model.Room, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Room, "", new { #class = "text-danger" })
</td>
<td>
#Html.EditorFor(model => model.Subject, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Subject, "", new { #class = "text-danger" })
</td>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-12">
<input type="button" name="add" value="Add" class="btn btn-default" onclick="addRow('AddSchedule')">
<input type="button" name="remove" value="Remove" class="btn btn-default" onclick="deleteRow('AddSchedule')">
</div>
</div>
and the controller
public ActionResult Create()
{
EmployeeViewModel employeeViewModel = new EmployeeViewModel();
ICollection<FacultySchedViewModel> schedViewModel = new List<FacultySchedViewModel>();
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(EmployeeViewModel employeeViewModel, ICollection<FacultySchedViewModel> schedViewModel)
{
if (ModelState.IsValid)
{
var emp = db.Employee.Create();
emp.ID = employeeViewModel.ID;
emp.LastName = employeeViewModel.LastName;
emp.FirstName = employeeViewModel.FirstName;
db.Employee.Add(emp);
if (schedViewModel != null)
{
var sched = db.FacultySchedule.Create();
foreach (var aaa in schedViewModel)
{
sched.EmployeeID = employeeViewModel.ID;
sched.Schedule = aaa.Schedule;
sched.Room = aaa.Room;
sched.Subject = aaa.Subject;
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
after running the create, and click the save button, EmployeeViewModel employeeViewModel is valid and not null, but the ICollection<FacultySchedViewModel> schedViewModel is null. I tried to use only EmployeeViewModel employeeViewModel but I do not know how to save it. I save the model in that way because there are default values and values to be extracted from other tables.

Trying to send datetime to controller via json

In my model I got a DateTime (FechaNac) format that I can't get it from a json.
public class Persona
{
public int Id { get; set; }
[Display(Name = "Nombre")]
[Required]
public string Nombre { get; set; }
[Display(Name = "Apellido")]
[Required]
public string Apellido { get; set; }
[Display(Name = "Fecha de nacimiento")]
[Required]
[DataType(DataType.Date)]
public DateTime FechaNac { get; set; }
[Display(Name = "Lugar")]
[Required]
public int Idlugar { get; set; }
}
In the controller I get most of the information of the model,
public JsonResult GetPostData(Persona jsonPersona)
{
Console.WriteLine(jsonPersona.ToString());
return Json(jsonPersona, "text/html", JsonRequestBehavior.AllowGet);
}
but I can't get the date, I tried a format it in javascript with in different ways with no success. The format is in ISO format (from the datepicker)
#using MVCprueba2.Models
#model MVCprueba2.Models.Persona
<div class="form-group">
#Html.LabelFor(model => model.Nombre, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Nombre)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Apellido, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Apellido)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FechaNac, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.JQueryUI().DatepickerFor(model => model.FechaNac)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Idlugar, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Idlugar)
</div>
</div>
<div id="mensaje">Mensaje</div>
<p><input type="submit" value="Save" id="guardarPersona" /></p>
<script type="text/javascript">
$(function () {
$("#guardarPersona").click(function () {
var persona = new Object();
persona.Nombre = $("#Nombre").val();
persona.Apellido = $("#Apellido").val();
persona.FechaNac = $('#FechaNac').datepicker("getDate"); //Solved [Typo]
persona.Idlugar = $("#Idlugar").val();
var jsonPersona = JSON.stringify(persona);
$.ajax({
url: "#Url.Action("GetPostData")",
type: "POST",
data: jsonPersona,
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (response) {
alert(response.responseText);
},
success: function (response) {
alert(response);
}
});
});
});
</script>
But in the controller, sadly, I don't get the date, how can I fix that ?
Seems to be working as expected
In the browser
Fecha de nacimiento: 29.10.2014
In the controller
FechaNac = {29.10.2014 00:00:00}

Should I bind html.dropdownlistfor in POST too in MVC 5?

This is my get
[Authorize]
public ActionResult SendMessage()
{
var model = new MessageModel();
var subjects = this.GetDistributionLists();
if (subjects != null) {
ViewBag.Subjects = new SelectList(subjects, "Value", "Text");
}
//Get patients list
var patients = this.GetPatientsList();
if (patients != null)
{
ViewBag.Patients = new SelectList(patients, "Value", "Text");
}
if (Request.IsAjaxRequest())
{
return PartialView("SendMessagePartial");
}
else
{
return View();
}
}
This is my post
[HttpPost]
[Authorize]
public ActionResult SendMessage(MessageModel model)
{
try {
if (ModelState.IsValid)
{
XmlDocument requestXml = XmlUtil.CreateRequestDocument("message", new
{
Message = model.MessageBody,
Type = model.Subject,
PatientID = model.PatientId,
RecipientID = model.RecipientId,
IsUrgent = model.IsUrgent ? "1" : "0"
});
//save message logic here
}
}
catch (Exception ex)
{
ModelState.AddModelError("ServerMessage", ex.Message);
}
if (Request.IsAjaxRequest())
{
return PartialView("SendMessagePartial", model);
}
else
{
return View(model);
}
}
This is my model
public class MessageModel
{
[DisplayName("RecipientId")]
public int RecipientId { get; set; }
[DisplayName("Sender")]
[StringLength(255)]
public string Sender { get; set; }
[DisplayName("SenderId")]
public int SenderId { get; set; }
[DisplayName("Message")]
[StringLength(4000)]
[Required]
public string MessageBody { get; set; }
[DisplayName("Subject")]
[StringLength(255)]
[Required]
public string Subject { get; set; }
[DisplayName("Patient")]
[Required]
public int PatientId { get; set; }
public bool IsUrgent { get; set; }
}
My View has a dropdownlistfor like
#Html.DropDownListFor(m => m.Subject, (SelectList)ViewBag.Subjects, new { #class = "form-control" })
When I GET, everything is fine.
When I POST, the data gets saved but in UI I get an error saying
The ViewData item that has the key 'Subject' is of type
'System.String' but must be of type 'IEnumerable'
Options are not posted back in the form. You will have to create them again:
[HttpPost]
[Authorize]
public ActionResult SendMessage(MessageModel model)
{
try {
if (ModelState.IsValid)
{
XmlDocument requestXml = XmlUtil.CreateRequestDocument("message", new
{
Message = model.MessageBody,
Type = model.Subject,
PatientID = model.PatientId,
RecipientID = model.RecipientId,
IsUrgent = model.IsUrgent ? "1" : "0"
});
//save message logic here
}
}
catch (Exception ex)
{
ModelState.AddModelError("ServerMessage", ex.Message);
}
var subjects = this.GetDistributionLists();
if (subjects != null) {
ViewBag.Subjects = new SelectList(subjects, "Value", "Text");
}
if (Request.IsAjaxRequest())
{
return PartialView("SendMessagePartial", model);
}
else
{
return View(model);
}
}

Resources