Validation not working in partial view - asp.net-mvc

I have an Index page which has two partial views: login and register.I am using data model validation.
Login.cshtml
#model Project.ViewModel.UserModel
<div style="position:inherit;">
#using (Html.BeginForm("_Login", "account"))
{
#Html.ValidationSummary(true)
<div class="label">#Html.Label("Username")</div>
<div class="field">#Html.TextBoxFor(m => m.Username)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Username)</div>
<div class="label">#Html.Label("Password")</div>
<div class="field">#Html.PasswordFor(m => m.Password)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Password)</div>
<input class="field" id="submit" type="submit" value="Login" />
}
Register.cshtml
#model Project.ViewModel.UserModel
<link href="~/Content/Site.css" rel="stylesheet" />
<div style="position: inherit; margin-top: 20px">
#using (Html.BeginForm("_Register","account"))
{
<div class="label">#Html.Label("Name")</div>
<div class="field">#Html.TextBoxFor(m => m.FullName)</div>
<div class="error">#Html.ValidationMessageFor(model => model.FullName)</div>
<div class="label">#Html.Label("Username")</div>
<div class="field">#Html.TextBoxFor(m => m.Username)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Username)</div>
<div class="label">#Html.Label("Password")</div>
<div class="field">#Html.PasswordFor(m => m.Password)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Password)</div>
<div class="label">#Html.Label("Confirm Password")</div>
<div class="field">#Html.PasswordFor(m => m.ConfirmPassword)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Password)</div>
<div class="label">#Html.Label("Email")</div>
<div class="field">#Html.TextBoxFor(m => m.Email)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Email)</div>
<div class="label">#Html.Label("Country")</div>
<div class="field">#Html.TextBoxFor(m => m.Country)</div>
<div class="error">#Html.ValidationMessageFor(model => model.Email)</div>
<input class="field" id="submit" type="submit" value="Sign Up" />
#Html.ValidationSummary()
}
Index.cshtml
#model Project.ViewModel.UserModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="regiserandlogin">
<div id="registerandlogin-header">
<label style="margin-left:50px;">Sign Up For Free!!!</label>
<label style="margin-left:350px;color:#28a1e2">Already Have An Account?</label>
</div>
<div id="registerbox">
#Html.Partial("_Register", new ProjectHub.ViewModel.UserModel())
</div>
<div id="loginbox">
#Html.Partial("_Login", new ProjectHub.ViewModel.UserModel())
</div>
public ViewResult _Register()
{
return View("_Register");
}
[HttpPost]
public ActionResult _Register(UserModel usermodel)
{
if (!ModelState.IsValid)
{
return View("Index");
}
try
{
FormsAuthentication.SetAuthCookie(usermodel.Username, false);
return RedirectToAction("activationemail", new {username= Username});
}
catch (Exception ae)
{
ModelState.AddModelError("", ae.Message);
return View();
}
}
public ViewResult _Login()
{
return View("_Login");
}
[HttpPost]
public ActionResult _Login(string username, string password)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(username, password))
{
if (!repository.IsVerified(username))
{
ModelState.AddModelError("","Account is not activated.;
return View();
}
FormsAuthentication.SetAuthCookie(username,false);
return RedirectToAction("Index","Home");
}
return RedirectToAction("Index", "account"); ;
}
else
{
ModelState.AddModelError("","Invalid Username/Password");
return View();
}
}
UserModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace ProjectHub.ViewModel
{
public class UserModel
{
[Required(ErrorMessage="Username is Required")]
public string Username { get; set; }
[Required(ErrorMessage = "Password is Required")]
public string Password { get; set; }
[Required(ErrorMessage = "Password is Required")]
public string ConfirmPassword { get; set; }
[Required(ErrorMessage = "Name is Required")]
public string FullName { get; set; }
[Required(ErrorMessage = "Email is Required")]
public string Email { get; set; }
[Required(ErrorMessage = "Country is Required")]
public string Country { get; set; }
}
}
When I press register button like this, I get a validation error
If I use RedirectToAction Method, I don't get the validation error.
Please advise me.

You should not use the same view model for both partials. You should have 2 different view models.
For example:
public class LoginViewModel
{
[Required(ErrorMessage="Username is Required")]
public string Username { get; set; }
[Required(ErrorMessage = "Password is Required")]
public string Password { get; set; }
}
and for the register partial:
public class RegisterViewModel
{
[Required(ErrorMessage="Username is Required")]
public string Username { get; set; }
[Required(ErrorMessage = "Password is Required")]
public string Password { get; set; }
[Required(ErrorMessage = "Password is Required")]
public string ConfirmPassword { get; set; }
[Required(ErrorMessage = "Name is Required")]
public string FullName { get; set; }
[Required(ErrorMessage = "Email is Required")]
public string Email { get; set; }
[Required(ErrorMessage = "Country is Required")]
public string Country { get; set; }
}
and then your main view model should aggregate those 2 view models:
public class MyViewModel
{
public LoginViewModel Login { get; set; }
public LoginViewModel Register { get; set; }
}
and then:
<div id="registerbox">
#Html.Partial("_Register", Model.Login)
</div>
<div id="loginbox">
#Html.Partial("_Login", Model.Register)
</div>

Add the following reference to the JQuery scripts in your View.
I went through the same situation and it solved my problem.
"~/Scripts/jquery.unobtrusive*"
"~/Scripts/jquery.validate*"

Related

MVC Two Class Within One Model Conflict while Saving data

My Code is as shown in below
MODEL
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyProject.Models
{
[Table("UserMaster")]
public partial class UserMaster
{
[Key]
public int UserID { get; set; }
[System.Web.Mvc.Remote("doesAlreadyExist", "User", HttpMethod = "POST", ErrorMessage = "User Number already exists. Please enter a different Number.")]
[Required(ErrorMessage = "Enter Personal No")]
[Display(Name = "User No")]
[StringLength(10)]
public string User No{ get; set; }
[Required(ErrorMessage = "Enter Password")]
[Display(Name = "Password")]
public string Password { get; set; }
[NotMapped]
[Compare("Password", ErrorMessage = "Password doesn't match.")]
[Display(Name = "Confirm Password")]
public string CPassword { get; set; }
}
public class UserChangePassMV
{
[Required]
[Display(Name = "Old Password")]
[DataType(DataType.Password)]
public string OldPassword { get; set; }
[Required]
[Display(Name = "New Password")]
[DataType(DataType.Password)]
public string NewPassword { get; set; }
[NotMapped]
[Display(Name = "Confirm Password")]
[DataType(DataType.Password)]
[Compare("NewPassword",ErrorMessage="Password Doesnt Match in User Change Password.")]
public string ConfirmPassword { get; set; }
}
public class ChangeAvatar
{
public byte[] Photo { get; set; }
public string ImgSrc { get; set; }
}
}
CONROLLER
[OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Client, NoStore = true)]
public ActionResult ChangeAvatar()
{
ChangeAvatar avatar = new Models.ChangeAvatar();
int uid = Convert.ToInt32(Session.GetDataFromSession<CommonUserSession>("CommonUserSession").UserID);
avatar.Photo = db.UserMasters.SingleOrDefault(x => x.UserID == uid).Photo;
if (avatar.Photo != null)
{
string imageBase64 = Convert.ToBase64String(avatar.Photo);
avatar.ImgSrc = string.Format("data:image/jpeg;base64,{0}", imageBase64);
}
return View("ChangeAvatar", "_Layout", avatar);
}
[HttpPost]
public ActionResult ChangeAvatar(HttpPostedFileBase file)
{
if (file == null)
{
ModelState.AddModelError("", "Select image to upload");
}
int uid = Convert.ToInt32(Session.GetDataFromSession<CommonUserSession>("CommonUserSession").UserID);
UserMaster Mem = db.UserMasters.SingleOrDefault(x => x.UserID == uid);
try
{
if (ModelState.IsValid)
{
string path = System.IO.Path.Combine(Server.MapPath("~/ProfileImg"), uid.ToString() + ".jpg");
// file is uploaded
file.SaveAs(path);
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
byte[] array = ms.GetBuffer();
Mem.Photo = array;
}
db.SaveChanges();
return RedirectToAction("ChangeAvatar");
}
}
catch (DbEntityValidationException ex)
{
var errorMessages = ex.EntityValidationErrors
.SelectMany(x => x.ValidationErrors)
.Select(x => x.ErrorMessage);
var fullErrorMessage = string.Join("; ", errorMessages);
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
HtmlHelperExtensions.LogError(ex);
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
catch (RetryLimitExceededException /* dex */)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
ChangeAvatar avatar = new Models.ChangeAvatar();
avatar.Photo = db.UserMasters.SingleOrDefault(x => x.UserID == uid).Photo;
if (avatar.Photo != null)
{
string imageBase64 = Convert.ToBase64String(avatar.Photo);
avatar.ImgSrc = string.Format("data:image/jpeg;base64,{0}", imageBase64);
}
return View(avatar);
}
VIEW
#model MyProject.Models.ChangeAvatar
#{
ViewBag.Title = "Change Avatar";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!-- BEGIN PAGE BAR -->
#section PageBreadcrumb{
<ul class="breadcrumb">
<li><i class="icon-home2 position-left"></i> Dashboard</li>
<li class="active">Change Avatar</li>
</ul>
}
<!-- END PAGE BAR -->
<div class="clearfix"></div>
#section PageJS{
<script type="text/javascript" src="~/assets/js/plugins/uploaders/fileinput.min.js"></script>
<script type="text/javascript" src="~/assets/js/pages/uploader_bootstrap.js"></script>
<script type="text/javascript">
if ('#ViewBag.Status' != "") {
var notice = new PNotify({
title: '#ViewBag.Status',
text: '#ViewBag.Msg',
addclass: 'bg-#ViewBag.Type' //primary,info,danger,success,warning
}).get().click(function () {
notice.remove(); //Click to remove
});
}
</script>
}
#using (Html.BeginForm("ChangeAvatar", "User", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="panel panel-flat">
<div class="panel-heading">
<h5 class="panel-title text-primary">Change Avatar</h5>
<div class="heading-elements">
<ul class="icons-list">
<li><a data-action="collapse"></a></li>
#*<li><a data-action="reload"></a></li>
<li><a data-action="close"></a></li>*#
</ul>
</div>
</div>
<div class="panel-body">
<div class="col-md-12">
<div class="form-group">
<label class="col-lg-2 control-label text-semibold">Avatar:</label>
<div class="col-lg-10">
<input type="file" name="file" class="file-input-custom" data-show-caption="true" data-show-upload="true" accept="image/*">
<span class="help-block">Show only image files for selection & preview.</span>
</div>
</div>
<div class="col-lg-12">
<div class="text-right">
<p>
<div class="text-right">
#*<button type="submit" class="btn btn-primary">Change <i class="icon-arrow-right14 position-right"></i></button>*#
</div>
</p>
</div>
</div>
</div>
</div>
</div>
}
Now while I am trying to save the data in Change Avatar it shows error of first model for
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. The validation errors are: Password doesn't match.
If i remove Compare part than it works, but i need that compare to confirm password
is this possible to work with two class like this?
Help me out I am stuck here.
Your UserMaster class has a CPassword property which will be set to null when you do db.UserMasters.SingleOrDefault(x => x.UserID == uid). You update Photo field and save the entity. db.SaveChanges(); triggers validation on your entity which is comparing password field values producing the exception. Both MVC and EF use data annotation attributes for validation. EF reads an attribute designed for presentation layer.
Think why do you need a CPassword field in your model class? It is not stored in the database. It is needed only to capture user input. Usually this is so-called viewModel class responsibility. In order to resolve the issue split UserMaster into separate classes.
public partial class UserMaster
{
[Key]
public int UserID { get; set; }
[Required]
[Display]
[StringLength(10)]
public string UserNo { get; set; }
[Required]
public string Password { get; set; }
}
public class UserMasterViewModel
{
public int UserID { get; set; }
[System.Web.Mvc.Remote("doesAlreadyExist", "User", HttpMethod = "POST", ErrorMessage = "User Number already exists. Please enter a different Number.")]
[Required(ErrorMessage = "Enter Personal No")]
[Display(Name = "User No")]
[StringLength(10)]
public string UserNo{ get; set; }
[Required(ErrorMessage = "Enter Password")]
[Display(Name = "Password")]
public string Password { get; set; }
[Compare("Password", ErrorMessage = "Password doesn't match.")]
[Display(Name = "Confirm Password")]
public string CPassword { get; set; }
}
Use UserMasterViewModel as a #model of your views. Perform dbModel <=> viewModel mappings in you controller methods.

Creating an MVC form using partial views each with complex models not binding to main model

I'm working on a form that has a main model being passed to the view. The model has sub-models within it, with partial views to render that content. The problem is that when I fill out the form, only those parameters on the main form get bound back to the model when the form is submitted.
I tried changing the Html.RenderPartial to a Html.EditorFor, and while it fixed my model binding problem, it removed all of my html formatting from the partial view.
Is there a way I can either bind my partial view elements to the main form model, or keep the html structure of my partial view using EditorFor?
Below is my code (I chopped out a bunch of stuff - especially from my main view - to try to simplify what I'm looking for).
This is my model:
public class ShipJobs
{
public String Job { get; set; }
public String Quote { get; set; }
public String PartName { get; set; }
public String Rev { get; set; }
public String Customer { get; set; }
public String CustomerName { get; set; }
public String TrackingNumber { get; set; }
public Int32 ShippedQuantity { get; set; }
public Boolean Certs { get; set; }
public Double ShippingCharges { get; set; }
public DateTime ShipDate { get; set; }
public String SelectedFreightTerms { get; set; }
public IEnumerable<SelectListItem> FreightTerms { get; set; }
public String SelectedContact { get; set; }
public IEnumerable<SelectListItem> Contacts { get; set; }
public String SelectedShipVia { get; set; }
public IEnumerable<SelectListItem> ShipVia { get; set; }
public Models.GreenFolders.Address Address { get; set; }
}
public class Address
{
public AddressType Type { get; set; }
public String ShipToId { get; set; }
public String ContactName { get; set; }
public String AddressName { get; set; }
public String Line1 { get; set; }
public String Line2 { get; set; }
public String City { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public String Phone { get; set; }
public SelectList ShipToAttnDropDown { get; set; }
public IEnumerable<SelectListItem> ShipToDropDown { get; set; }
}
Controller:
public ActionResult ShipJobs(String Job, Models.Shipping.ShippingModel.ShipJobs Packlist, Models.GreenFolders.Address ShipAddress, String Submit = "")
{
var Model = new Models.Shipping.ShippingModel.ShipJobs();
if (Submit == "loadjob")
{
var shippingHelper = new BLL.Shipping.ShippingMethods(_company);
Model = shippingHelper.GetShipJobModel(Job);
Model.Address = shippingHelper.GetShipAddress(Job);
}
else if (Submit == "createpacklist")
{
}
ViewBag.Company = _company.ToString();
return View(Model);
}
Main View:
#model Models.Shipping.ShippingModel.ShipJobs
#{
ViewBag.Title = "ShipJobs";
String Company = ViewBag.Company.ToString();
}
#using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal" }))
{
<div class="row">
<div class="col-md-6">
<!-- Basic Form Elements Block -->
<div class="block">
<!-- Basic Form Elements Title -->
<div class="block-title">
<h2>Load <strong>Job</strong></h2>
</div>
<!-- END Form Elements Title -->
<!-- Basic Form Elements Content -->
#using (Html.BeginForm("ShipJobs", "Shipping", FormMethod.Post, new { Class = "form-horizontal form-bordered" }))
{
<div class="form-group">
<label class="col-md-3 control-label" for="example-text-input">Job Number</label>
<div class="col-md-9">
#Html.TextBoxFor(model => model.Job, new { id = "example-text-input", Name = "Job", Class = "form-control" })
</div>
</div>
<div class="form-group form-actions">
<div class="col-md-9 col-md-offset-3">
<button type="submit" class="btn btn-sm btn-primary" name="submit" value="loadjob"><i class="fa fa-angle-right"></i> Load Job Info</button>
<button type="reset" class="btn btn-sm btn-warning"><i class="fa fa-repeat"></i> Reset</button>
</div>
</div>
}
</div>
</div>
<div class="col-md-6">
#if (Model.Address != null && Model.Address != null)
{
#Html.EditorFor(model => model.Address)
//Html.RenderPartial("../Shared/_Address", Model.ShipInfo);
}
</div>
#Html.HiddenFor(model => model.Quote)
#Html.HiddenFor(model => Company)
</div>
}
Partial view:
#model Models.GreenFolders.Address
<!-- Block -->
<div class="block">
<div class="block-title">
#if(Model.Type == Models.GreenFolders.AddressType.Shipping)
{
<h2 style="float: right; margin-top: -9px; margin-right: -10px;">
<div class="dropdown shiptoddl">
<button class="btn btn-default dropdown-toggle" type="button" id="shiptoddl" data-toggle="dropdown" aria-expanded="true">
#Model.ShipToDropDown.Where(x => x.Selected).FirstOrDefault().Text
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
#foreach (SelectListItem selectlistitem in Model.ShipToDropDown)
{
<li role="presentation"><a role="menuitem" tabindex="-1" href="#" data-value="#selectlistitem.Value" data-selected="#selectlistitem.Selected">#selectlistitem.Text</a></li>
}
</ul>
</div>
#*#Html.DropDownList("shiptoddl", (SelectList)Model.ShipToDropDown, new { #class = "shiptoddl", id = "shiptoddl" })*#
</h2>
}
<h4><strong>#Model.Type.ToString()</strong> Address</h4>
</div>
#{ Html.RenderPartial("../Shared/_AddressDetails", Model); }
</div>
<!-- END Block -->

Html.TextBoxFor() does not generate any html markup

I've got 4 shared EditorTemplates: Tab, Group, Line & Item.
Tab.cshtml:
#model AWMCCRM.Web.ViewModels.Tab
#Html.HiddenFor(vm => vm.Name)
<div id="tab-#Model.Name.Replace(" ", string.Empty)" class="tab-content">
#Html.EditorFor(vm => vm.Groups)
</div>
Group.cshtml:
#model AWMCCRM.Web.ViewModels.Group
#Html.HiddenFor(vm => vm.Name)
<fieldset>
<legend>#Model.Name</legend>
#Html.EditorFor(vm => vm.Lines)
</fieldset>
Line.cshtml:
#model AWMCCRM.Web.ViewModels.Line
#Html.HiddenFor(vm => vm.Name)
#Html.EditorFor(vm => vm.Items)
Item.cshtml:
#model AWMCCRM.Web.ViewModels.Item
<div class="#Model.DivClass">
<p class="#Model.PClass">
Html.LabelFor(vm => vm.ValueString, Model.Name);
Html.TextBoxFor(vm => vm.ValueString);
</p>
</div>
Corresponding ViewModels:
public class Tab
{
public string Name { get; set; }
public List<Group> Groups { get; set; }
}
public class Group
{
public string Name { get; set; }
public List<Line> Lines { get; set; }
}
public class Line
{
public string Name { get; set; }
public List<Item> Items { get; set; }
}
public class Item
{
public string Name { get; set; }
public string Description { get; set; }
public string ValueString { get; set; }
public string DivClass { get; set; }
public string PClass { get; set; }
}
In my main View I have this:
#Html.EditorFor(vm => vm.Tabs)
The code that gets generated looks like this:
<div id="tab-Tab-1" class="tab-content">
<input id="Tabs_0__group_Name" name="Tabs[0].group.Name" type="hidden" value="Group0" />
<fieldset>
<legend>Group0</legend>
<input id="Tabs_0__group_line_Name" name="Tabs[0].group.line.Name" type="hidden" value="Line0" />
<div class="_20">
<p class="">
</p>
</div>
</fieldset>
</div>
As you can see, the div and the p gets generated, but there is no textbox or label.
I have also tried this in the item template instead, but it didn't work either:
Html.TextBoxFor(vm => Model.ValueString);
Any ideas why or what I need to do?
Thanks
Ok, I'm almost too embarrassed to post the solution but here it is...
I was missing the '#' in the beginning of the lines;
in my item.cshtml
Html.LabelFor(vm => vm.ValueString, Model.Name);
Html.TextBoxFor(vm => vm.ValueString);
should be
#Html.LabelFor(vm => vm.ValueString, Model.Name);
#Html.TextBoxFor(vm => vm.ValueString);

Asp.net mvc dropdown list

I am having a bugger of a time trying to figure out where I am going wrong. Scenario is this. Trying to add an object that has a foreign key in it with mvc entity framework.
public class Person
{
[Key]
public virtual int PersonId { get; set; }
[Display(Name = "First Name")]
[Required]
[MaxLength(50)]
public virtual string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required]
[MaxLength(50)]
public virtual string LastName { get; set; }
[Required]
public virtual int TestItem { get; set; }
[Required(ErrorMessage = "Please Select an Employee Type")]
public virtual EmployeeType EmployeeTypeId { get; set; }
}
public class EmployeeType
{
[Key]
public virtual int EmployeeTypeId { get; set; }
[Required]
public virtual string EmployeeTypeName { get; set; }
}
Those are the two pocos for the entities.
public ActionResult Create()
{
PersonViewModel pv = new PersonViewModel();
ViewBag.EmployeeTypeSelect= new SelectList(db.EmployeeTypes, "EmployeeTypeId", "EmployeeTypeName");
return View(pv);
}
//
// POST: /Person/Create
[HttpPost]
public ActionResult Create(PersonViewModel personVM)
{
if (ModelState.IsValid)
{
Person person = new Person();
person.EmployeeTypeId = personVM.EmployeeTypeId;
person.FirstName = personVM.FirstName;
person.LastName = personVM.LastName;
person.TestItem = personVM.TestItem;
db.Persons.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(personVM);
}
That is the controller.
#model MvcApplication3.Models.PersonViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>PersonViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.TestItem)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TestItem)
#Html.ValidationMessageFor(model => model.TestItem)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.EmployeeTypeId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model=>model.EmployeeTypeId,(SelectList)ViewBag.EmployeeTypeSelect)
#Html.ValidationMessageFor(model => model.EmployeeTypeId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
That is the view.
Everything works fine with the view off the initial get, but when I post the EmployeeTypeId has a null value. I check the source and the select list is fine, has proper values and text. Please help as I have no clue where i am going wrong.
Thanks
Try adding in Html.EndForm() in the HTML after all of the values you wish to post and see if that fixes the problem?
Your Person and EmployeeType class needs to have a default (empty) constructor for the model binding to work -
public class EmployeeType
{
[Key]
public virtual int EmployeeTypeId { get; set; }
[Required]
public virtual string EmployeeTypeName { get; set; }
public EmployeeType()
{
}
}
public class Person {
[Key]
public virtual int PersonId { get; set; }
[Display(Name = "First Name")]
[Required]
[MaxLength(50)]
public virtual string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required]
[MaxLength(50)]
public virtual string LastName { get; set; }
[Required]
public virtual int TestItem { get; set; }
[Required(ErrorMessage = "Please Select an Employee Type")]
public virtual EmployeeType EmployeeTypeId { get; set; }
public Person()
{
EmployeeTypeId = new EmployeeType();
}
}
Also, try in your view, making it
#Html.DropDownListFor(model=>model.EmployeeTypeId.EmployeeTypeId,(SelectList)ViewBag.EmployeeTypeSelect)

only show the errormessage when email is invalid

I work in ASP MVC3. I have a model for the input of the contact information of a customer.
The information is required. When the viewstat is not valid the textboxes must have a red border (this works) en no errormessage. But when the emailinput is invalid the the error must be visible on the view. So only the errormessage of the emailannotation must be visible and not of the requiredannotation. I have no idea how to do this.
model:
[Required]
public string FirstName { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string PostalCode { get; set; }
[Required]
public string City { get; set; }
[Required]
public string Country { get; set; }
[Required]
public string PhoneNumber { get; set; }
public string Fax { get; set; }
[Required]
[Email]
public string Email { get; set; }
view:
<div class="row-fluid">
<div class="span6">
<div data-role="fieldcontain" class="ui-hide-label">
<label for=#Lingo.language.Obj_Telefoon>#Lingo.language.Obj_Telefoon</label>
<span>#Html.TextBoxFor(m => m.PhoneNumber, new { style = "width:90%!important;", placeholder = #Lingo.language.Obj_Telefoon })</span>
</div>
</div>
<div class="span6">
<div data-role="fieldcontain" class="ui-hide-label">
<label for=#Lingo.language.Obj_Fax>#Lingo.language.Obj_Fax</label>
<span>#Html.TextBoxFor(m => m.Fax, new { placeholder = #Lingo.language.Obj_Fax })</span>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div data-role="fieldcontain" class="ui-hide-label">
<label for=#Lingo.language.Obj_Email>#Lingo.language.Obj_Email</label>
<span>#Html.TextBoxFor(m => m.Email, new { style = "width:98%!important;", placeholder = #Lingo.language.Obj_Email })</span>
<span>#Html.ValidationMessageFor(m => m.Email)</span>
</div>
</div>
</div>
write with required message like this:
[Required( ErrorMessage = "The first name is required" )]
public string FirstName { get; set; }
If you want it to be required, but don't want to show the "required" error message, you could set the message to be a single space (to avoid the run-time error "Either ErrorMessageString or ErrorMessageResourceName must be set, but not both.")
[Required(ErrorMessage = " ")]
[Email(ErrorMessage = "Must be a valid email address.")]
public string Email { get; set; }
If you don't already have the Email attribute, you can create a class file (e.g. EmailAttribute.cs) containing:
using System.ComponentModel.DataAnnotations;
public class EmailAttribute: RegularExpressionAttribute {
public EmailAttribute()
: base(#"^[a-zA-Z0-9._%+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$") { }
}

Resources