I am building a Form in my view based on a View Model. the View model has [Required] on every field and Validation rules, but when checking the Model.IsValid it keeps coming back true even when all of the form fields are blank or null. Here is the View:
#model CommunityWildlifeHabitat.ViewModel.CreateAdminViewModel
#{
ViewBag.Title = "CreateAdmin";
}
<h2>Create Admin</h2>
#using (Html.BeginForm("CreateAdmin", "Admin", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-6 control-label" })
<div class="col-md-6">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.FirstName, new { #class = "col-md-6 control-label" })
<div class="col-md-6">
#Html.TextBoxFor(m => m.FirstName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.LastName, new { #class = "col-md-6 control-label" })
<div class="col-md-6">
#Html.TextBoxFor(m => m.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-6 control-label" })
<div class="col-md-6">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-6 control-label" })
<div class="col-md-6">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.ConfirmPassword, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-6">
<input type="submit" class="btn btn-habitat" value="Create Admin" />
</div>
</div>
}
Here is my ViewModel
public class CreateAdminViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
Here is the Controller get and post
[Authorize]
public ActionResult CreateAdmin(int? id)
{
var model = new CreateAdminViewModel();
if (id == null) { return RedirectToAction("Index", "Communities"); }
if (User.Identity.IsAuthenticated)
{
var userId = User.Identity.GetUserId();
var superUser = db.CommunityTeams.Where(x => x.UserId == userId && x.RoleId == 4).Any();
// If User is not a SuperUser (Administrator)
if (superUser == false)
return RedirectToAction("Index", "Communities");
}
return View(model);
}
[Authorize]
[HttpPost]
public ActionResult CreateAdmin(FormCollection fc)
{
var model = new CreateAdminViewModel();
model.Email = fc["Email"];
model.FirstName = fc["FirstName"];
model.LastName = fc["LastName"];
model.Password = fc["Password"];
model.ConfirmPassword = fc["ConfirmPassword"];
if (ModelState.IsValid)
{ }
return RedirectToAction("index", "Admin");
}
On your HttpPost you have a model type of FormCollection
public ActionResult CreateAdmin(FormCollection fc)
Should it be of your model type? Else always true state?
public ActionResult CreateAdmin(CreateAdminViewModel fc)
Related
I must not be searching with the correct phrases. This is a simple concept and I’ve done it in other languages and frameworks with ease.
I’m saving the UserID for the person who created the record and the UserID who last updated the record. Instead of displaying the UserID, I want to display the User.FirstName + ‘ ‘ + User.LastName.
The way I have it currently the LastEditBy and CreateBy is displayed on the page as blank.
Controller: I get the customer model and manually map the model to the customerViewModel then pass it to my partial view.
public ActionResult Edit(int customerId)
{
Customer customer = DbContext.Customers.FirstOrDefault(x => x.CustomerId == customerId);
CustomerViewModel customerViewModel = MapToViewModel(customer);
customerViewModel.UserSelectList = GetUserGroupList();
UserManager<ApplicationUser> _userManager = HttpContext.GetOwinContext().Get<ApplicationUserManager>();
var CreateByUser = _userManager.FindById(customerViewModel.CreateById);
var EditByUser = _userManager.FindById(customerViewModel.LastEditById);
customerViewModel.CreateBy = CreateByUser.FirstName + " " + CreateByUser.LastName;
customerViewModel.LastEditBy = EditByUser.FirstName + " " + EditByUser.LastName;
if (Request.IsAjaxRequest()) {
return PartialView("_CustomerEditPartial", customerViewModel);
}
return View("_CustomerEditPartial", customerViewModel);
}
The CustomerViewModel:
public class CustomerViewModel : DbContext{
public CustomerViewModel(): base("name=CustomerViewModel")
{
}
[Key]
public int CustomerId { get; set; }
[MaxLength(128), ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public SelectList UserSelectList { get; set; }
#region additional Fields
// This overrides default conventions or data annotations
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime CreateDate { get; set; } = DateTime.Now;
public string CreateById { get; set; }
[NotMapped]
public string CreateBy { get; set; }
public string LastEditById { get; set; }
[NotMapped]
public string LastEditBy { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime LastEditDate { get; set; } = DateTime.Now;
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class UserGroupList
{
public string Value { get; set; }
public string Text { get; set; }
}
My partial view page: _CustomerEditPartial.cshtml
#model WOA.ViewModels.CustomerViewModel
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" daa-dismiss="modal" aria-hidden="True">x</button>
<h4 class="modal-title">Edit Customer</h4>
</div>
#using (Ajax.BeginForm("Edit", "Customers", null, new AjaxOptions { HttpMethod = "Post", OnFailure = "OnFail" }, new { #class = "form-horizontal", role = "form" })) {
<div class="modal-body">
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.CustomerId)
<div class="form-group">
#Html.LabelFor(model => model.UserId, "UserId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.UserId, ViewData.Model.UserSelectList, "Select One", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UserId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreateDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.CreateDate, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreateBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.CreateBy, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastEditBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.LastEditBy, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastEditDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.LastEditDate, new { #readonly = "readonly" })
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Save changes" />
</div>
</div>
</div>
<script type="text/javascript">
function OnSuccess() {
alert("success");
}
function OnFail() {
alert("fail");
}
function OnComplete() {
alert("Complete");
}
</script>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I have updated my code, it is working now, however I do not believe it is the proper way to do this.
I believe I should be able to return the additional values I need via Linq on the initial call and not make two more trips to the database for the additional values.
I have not been able to figure out a way to make this work with Linq.
Thank you in advance for your time and effort.
I am testing an ASP.NET MVC 5 application with Visual Studio 2017 Community edition.
I am trying to save Assort model to database with following code.
I am navigating to Assort Create page with URL /Assort/Create/1A.
The parameter 1A is needed on create page of Assort as I need to display some additional information from that parameter on create page itself.
But when I submit the data, 1A parameter value is being inserted as ID value of Assort model, and thus my ModelState is invalid and I am unable to save data.
Can anyone help me?
MODEL
public class Assort
{
[Key]
public int ID { get; set; }
[Display(Name = "Assort No")]
[Required(ErrorMessage = "Assort No can not be empty.")]
public int ASSORTNO { get; set; }
[Display(Name = "Date")]
[Required(ErrorMessage = "Date can not be empty.")]
public DateTime DATE { get; set; }
[Display(Name = "RFNO")]
[Required(ErrorMessage = "RFNO can not be empty.")]
[StringLength(50)]
public string RFNO { get; set; }
[Display(Name = "Manager")]
[Required(ErrorMessage = "Manager can not be empty.")]
public int MANAGER { get; set; }
[Display(Name = "Caret")]
[Required(ErrorMessage = "Caret can not be empty.")]
public decimal CARET { get; set; }
[Display(Name = "MFG Size")]
[Required(ErrorMessage = "MFG Size can not be empty.")]
public decimal MFGSIZE { get; set; }
[Display(Name = "Total PCS")]
[Required(ErrorMessage = "Total PCS can not be empty.")]
public decimal TOTALPCS { get; set; }
[StringLength(50)]
public string APPROVALSTATUS { get; set; }
[Display(Name = "Details")]
public string DETAILS { get; set; }
[ScaffoldColumn(false)]
public DateTime CREATE_TIMESTAMP { get; set; }
[ScaffoldColumn(false)]
public DateTime LAST_EDIT_TIMESTAMP { get; set; }
[UIHint("AssortReturn")]
public virtual List<AssortReturn> AssortReturn { get; set; }
public Assort()
{
AssortReturn = new List<AssortReturnModel.AssortReturn>();
}
[ForeignKey("RFNO")]
public virtual Rough rough { get; set; }
}
ACTION
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Assort assort)
{
if (ModelState.IsValid)
{
assort.APPROVALSTATUS = "NOT APPROVED";
assort.CREATE_TIMESTAMP = DateTime.Now;
assort.LAST_EDIT_TIMESTAMP = DateTime.Now;
db.Assorts.Add(assort);
db.SaveChanges();
return RedirectToAction("Index");
}
Initialize(assort.RFNO,"CREATE");
return View(assort);
}
VIEW
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ASSORTNO, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ASSORTNO, new { htmlAttributes = new {#readonly="readonly",#Value=ViewBag.ASSORTNO, #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ASSORTNO, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DATE, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DATE, new { htmlAttributes = new {#autofocus="autofocus",#Value=ViewBag.CURRENTDATE, #class = "form-control date" } })
#Html.ValidationMessageFor(model => model.DATE, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RFNO, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.RFNO, new { htmlAttributes = new { #readonly = "readonly", #Value = ViewBag.RFNO, #class = "form-control" } })
#Html.TextBox("AVAILABLECARET",(decimal)ViewBag.AVAILABLECARET,new {#class="form-control txtAvailablecaret",#readonly="readonly" })
#Html.ValidationMessageFor(model => model.RFNO, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MANAGER, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.EditorFor(model => model.MANAGER, new { htmlAttributes = new { #class = "form-control" } })*#
#Html.DropDownListFor(model => model.MANAGER, new SelectList(ViewBag.MANAGERLIST, "ID", "USERNAME"), "Select Manager", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.MANAGER, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CARET, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CARET, new { htmlAttributes = new { #class = "form-control txtCaret" } })
#Html.ValidationMessageFor(model => model.CARET, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MFGSIZE, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MFGSIZE, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MFGSIZE, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TOTALPCS, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TOTALPCS, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TOTALPCS, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DETAILS, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DETAILS, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DETAILS, "", 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 btnCreate" />
</div>
</div>
</div>
}
This is because of the default route, which is handling your request. It looks like:
{controller}/{action}/{id}
And so A1 gets bound to ID. If you want a different behavior, say A1 is still a part of the URL, but binds to a different param, say "name", you need a new route for that:
routes.MapRoute(
name: "CreateAssort",
url: "Assort/Create/{name}",
defaults: new { controller = "Assort", action = "Create"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Now "name" will hold A1 and not ID. Notice how your custom route comes before the default one. This is important - routing picks the first route that matches the request.
What you can do is add a hidden input field named ID to your view.
When the form will be submitted, the value from this field will take precedence over the one from your route i.e. '1A' and the model would have ID as 0 if you don't set the hidden input's value.
I had same issue. But problem is when you creating an model.
You need to have two methods.
[HttpGet] // http://localhost/Assort/Create/1
public ActionResult Create(int Id)
{
ModelState.Remove(nameof(Id)); // this will remove binding
var assort = new Assort()
{
Id = 'whatever',
....
};
return View(assort);
}
[HttpPost] // http://localhost/Assort/Create/
public ActionResult Create(Models.Assort assort)
{
if (ModelState.IsValid)
{
assort.APPROVALSTATUS = "NOT APPROVED";
assort.CREATE_TIMESTAMP = DateTime.Now;
assort.LAST_EDIT_TIMESTAMP = DateTime.Now;
db.Assorts.Add(assort);
db.SaveChanges();
return RedirectToAction("Index");
}
Initialize(assort.RFNO,"CREATE");
return View(assort);
}
C# ASP MVC Route Model ID bug
I'm currently working on user account and so far i've managed to work upon register and login panel with email confirmation process. Here i'm stuck in forget password option. I'm using ado.net entity framework. All i have to do is to change password for the registered email. This is what i've done so far.
Note: getting the error in controller action method
the entity type is not part of the model for the current context
Edit
I have a table named registration attached to the DBContext class. And i'm trying to update the records (particularly the password field) for the forger password option. I made the property class UpdateAcccount.cs with validation as attached below. In order to update the password, I retrieved the row matching with email id. And then transferring the updated password in the database.
This time i'm getting the error of "password does not match" although there's no field of confirm password in the database(registration table) + i even tried to use bind(exclude) attribute for confirm password but that didn't work either.
Controller class
[HttpPost]
public ActionResult UpdateAccount(UpdateAccount account)
{
string message = "";
bool status = false;
if (ModelState.IsValid)
{
account.Password = Crypto.Hash(account.Password);
account.ConfirmPassword = Crypto.Hash(account.ConfirmPassword);
using (TravelGuide1Entities entity = new TravelGuide1Entities())
{
try
{
var v = entity.Registrations.Where(a => a.Email == account.Email).FirstOrDefault();
if (v != null)
{
v.Password = account.Password;
entity.Entry(v).State = System.Data.Entity.EntityState.Modified;
entity.SaveChanges();
return RedirectToAction("Login");
}
}
catch(Exception e)
{
}
}
}
return View();
}
UpdateAccount.cs
public class UpdateAccount
{
[Display(Name = "Email")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Email id required")]
public string Email { get; set; }
[Display(Name = "New Password")]
[Required(AllowEmptyStrings = false, ErrorMessage = "Password required")]
[DataType(DataType.Password)]
[MinLength(6, ErrorMessage = "Minimum 6 character required")]
public string Password { get; set; }
[Display(Name = "Confirm Password")]
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "Password do not match")]
public string ConfirmPassword { get; set; }
}
UpdateAccount.cshtml
#model Travel.Models.UpdateAccount
#{
ViewBag.Title = "UpdateAccount";
}
<h2>UpdateAccount</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>UpdateAccount</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Email, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Email, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ConfirmPassword, "", 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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I am having following ViewModel, and corresponding two models.
I am displaying data from this ViewModel on a view, but when I post data to update, following error occurs
The model item passed into the dictionary is of type 'WebMSM.Models.ComplainDetailsVm', but this dictionary requires a model item of type 'WebMSM.Models.REPAIRING'.
public partial class ComplainDetailsVm
{
public virtual REPAIRING REPAIRINGs { get; set; }
public virtual COMPLAIN COMPLAINs { get; set; }
}
REPAIRING.cs
public partial class REPAIRING
{
[Key]
[DisplayName("JOBSHEET NO")]
public int JOBSHEET_NO { get; set; }
[DisplayName("IN TIME")]
public Nullable<System.DateTime> IN_TIMESTAMP { get; set; }
[DisplayName("CREATE TIME")]
public Nullable<System.DateTime> CREATE_TIMESTAMP { get; set; }
[DisplayName("LAST EDIT TIME")]
public Nullable<System.DateTime> LAST_EDIT_TIMESTAMP { get; set; }
}
COMPLAIN.cs
public partial class COMPLAIN
{
[Key]
[DisplayName("JOBSHEET NO")]
public int JOBSHEET_NO { get; set; }
[Required]
[DisplayName("COMPANY NAME")]
public string COMPANY_NAME { get; set; }
[Required]
[DisplayName("MODEL NAME")]
public string MODEL_NAME { get; set; }
}
CONTROLLER ACTION
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int? id,ComplainDetailsVm model)
{
if (ModelState.IsValid)
{
var r = model.REPAIRINGs;
var c = model.COMPLAINs;
db.Entry(r).State = EntityState.Modified;
db.SaveChanges();
}
return View(model);
}
UPDATE
VIEW
#model WebMSM.Models.ComplainDetailsVm
#{
ViewBag.Title = "EditRepairingComplain";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.REPAIRINGs.JOBSHEET_NO)
#Html.HiddenFor(model => model.COMPLAINs.JOBSHEET_NO)
<div class="form-group">
#Html.LabelFor(model => model.COMPLAINs.COMPANY_NAME,
htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.TextBoxFor(model => model.COMPLAINs.COMPANY_NAME, new { #class = "form-control", #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.COMPLAINs.COMPANY_NAME, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.COMPLAINs.MODEL_NAME, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.TextBoxFor(model => model.COMPLAINs.MODEL_NAME, new { #class = "form-control", #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.COMPLAINs.MODEL_NAME, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.REPAIRINGs.IN_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.REPAIRINGs.IN_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.REPAIRINGs.IN_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.REPAIRINGs.CREATE_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.REPAIRINGs.CREATE_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.REPAIRINGs.CREATE_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.REPAIRINGs.LAST_EDIT_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.REPAIRINGs.LAST_EDIT_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.REPAIRINGs.LAST_EDIT_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-6">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
UPDATE ADDED GET METHOD
// GET: Repairing/Edit/5
public ActionResult Edit(int? id)
{
var vm = new ComplainDetailsVm();
var r = db.REPAIRINGs.Find(id);
var c = db.COMPLAINs.Find(id);
if (r != null)
{
vm.REPAIRINGs = r;
vm.COMPLAINs = c;
}
//ViewData["LIST_ESTIMATE_AMOUNT_OK_FROM_CUSTOMER"] = lstOKNOTOK;
return View("EditRepairingComplain",vm);
}
Thanks.
You can have your Views recognize your ViewModel in two ways: you can have the MVC framework figure that out for you, or you can use strongly typed views
In your case, your view is strongly typed but refers to the wrong object class. This can happen if you copied your view from some other file. You should see the following line on your cshtml file:
#model WebMSM.Models.REPAIRING
replace this with:
#model WebMSM.Models.ComplainDetailsVm
and you should no longer get the error.
Edit:
worth to mention that these lines should be on top of the cshtml file returned by the action methods.
I have this model :
[Required(ErrorMessage = "Please provide a valid EmailAddress")]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required(ErrorMessage = "Please provide a company name")]
[Display(Name = "Company")]
public string CompanyName { get; set; }
[Required(ErrorMessage = "Please provide a username")]
[Display(Name = "Username")]
public string UserName { get; set; }
[Required(ErrorMessage = "Please select at least one language")]
public int[] SelectedLanguages { get; set; }
[Required(ErrorMessage = "Please select at least one business unit")]
public int[] SelectedBusinessUnits { get; set; }
Now when I do a post from my form using this model and I don't provide any of the values, I only get errormessages for Email, Company and UserName.
I don't get messages for the SelectedLanguages or the SelectedBusinessUnits.
What am i doing wrong?
THis is the view
#using (Html.BeginForm("Register", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Create a new account.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.CompanyName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.CompanyName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.UserName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.UserName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#foreach (var la in Model.Languages)
{
<input type="checkbox"
name="SelectedLanguages" value="#la.Id" id="#la.Id" />
<label for="#la">#la.Title</label>
}
</div>
<div class="form-group">
#foreach (var bu in Model.BusinessUnits)
{
<input type="checkbox"
name="SelectedBusinessUnits" value="#bu.Id" id="#bu.Id" />
<label for="#bu.Id">#bu.Title</label>
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Register" />
</div>
</div>
}
I think you have to go the way of writing a custom validation routine accompanied with a ValidationAttribute. Don't think a simple "out-of-the-box" validator exists for checking if one or more values are present in an array.
Check out this SO post to point you in the right direction.
Basic setup:
public class ArrayContainsValueAttribute: ValidationAttribute
{
// your checks here (pseudo)
if(!array.Any())
return false;
return true;
}
[ArrayContainsValue(ErrorMessage = "Please select at least one business unit")]
public int[] SelectedBusinessUnits { get; set; }