I'm very new with MVC, so bear with me, but I can't seem to bind a value from a SelectList to an instance of the selected object during a postback in MVC 4.
Suppose I have to create a Teacher as a member of a School. I have a ViewModel class defined as such:
public class RegisterTeacherModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required]
[Display(Name = "School")]
public School SelectedSchool { get; set; }
[ScaffoldColumn(false)]
public Guid UserId
{
get;
set;
}
public SelectList PossibleSchools
{
get;
private set;
}
public RegisterTeacherModel(IRepository<School> schoolRepo)
{
PossibleSchools = new SelectList(schoolRepo, "Id", "Name");
}
}
And my View:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>RegisterTeacherModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SelectedSchool)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedSchool, Model.PossibleSchools)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
And finally, my Controller method:
[HttpPost, ActionName("Create")]
public ActionResult CreateTeacher(RegisterTeacherModel teacherModel)
{
if (ModelState.IsValid)
{
try
{
...
}
}
}
But when I receive the RegisterTeacherModel object back in my Create method in the Controller, SelectedSchool is always null. I must be missing something in the way the model binder re-creates the object references on postback. Can anyone point me in the right direction?
I think you touched on it with your second post: Try pointing the initial code to Model.SelectedSchool.<IdProperty>
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedSchool.**<IdProperty>**, Model.PossibleSchools)
</div>
Well, I found a workaround. I still don't know if I'm missing something, but instead of using a School object in my ViewModel, I replaced it with the SelectedSchoolId as such:
public class RegisterTeacherModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
[Required]
[Display(Name = "School")]
public int SelectedSchoolId { get; set; }
...
}
And change my View dropdown to use this instead:
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedSchoolId, Model.PossibleSchools)
</div>
And then in my controller, when creating the real model objects I can simply pull the School object from the School repository and associate it with the real Teacher object.
Related
I'm passing a ViewModel back from my View to the Controller via a form HttpPost. However, the values returned are always NULL.
ViewModel
public class vmCompanyAddress
{
public StatelyTechAdmin.Models.Company Company { get; set; }
public StatelyTechAdmin.Models.CompanyAddress Address { get; set; }
public SelectList Counties { get; set; }
}
Company Class Model
public class Company
{
[Key]
public virtual long CompanyId { get; set; }
[Required]
[Display(Name = "Company Name")]
public virtual string Name { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual IEnumerable<CompanyAddress> CompanyAddresses { get; set; }
}
CompanyAddress Class Model
public class CompanyAddress
{
[Key]
public virtual long CompanyAddressId { get; set; }
[Required]
public virtual long CompanyId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[Required]
public virtual int CopmanyAddressTypeId { get; set; }
[ForeignKey("CopmanyAddressTypeId")]
public virtual CompanyAddressType CompanyAddressType { get; set; }
[Display(Name = "Address 1")]
public virtual string Address1 { get; set; }
[Display(Name = "Address 2")]
public virtual string Address2 {get; set; }
[Display(Name = "Town")]
public virtual string Town { get; set; }
[Display(Name = "City")]
public virtual string City { get; set; }
[Required]
public virtual long CountyId { get; set; }
[ForeignKey("CountyId")]
[Display(Name = "County")]
public virtual County County { get; set; }
[Required]
[Display(Name = "Postal Code")]
public virtual string PostalCode { get; set; }
public virtual DateTime CreatedDate { get; set; }
}
Controller (get):
// GET: /Company/Create
public ActionResult Create()
{
vmCompanyAddress vm = new vmCompanyAddress();
vm.Counties = new SelectList(db.County, "CountyId", "Name", -1);
//vm.Address = new CompanyAddress();
//vm.Company = new Company();
return View(vm);
}
Controller (post):
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(vmCompanyAddress company)
{
if (ModelState.IsValid)
{
db.Companies.Add(company.Company);
//Amend Address Company & Address Type before save to DB
company.Address.CompanyId = company.Company.CompanyId;
company.Address.CopmanyAddressTypeId = 1;
db.CompanyAddress.Add(company.Address);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(company);
}
View (create)
#model StatelyTechAdmin.ViewModels.vmCompanyAddress
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Company</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Company.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Company.Name)
#Html.ValidationMessageFor(model => model.Company.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Company.CreatedDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Company.CreatedDate)
#Html.ValidationMessageFor(model => model.Company.CreatedDate)
</div>
#* Invoice Address *#
<div class="editor-label">
#Html.LabelFor(model => model.Address.Address1)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address.Address1)
#Html.ValidationMessageFor(model => model.Address.Address1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Address.Address2)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address.Address2)
#Html.ValidationMessageFor(model => model.Address.Address2)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Address.Town)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address.Town)
#Html.ValidationMessageFor(model => model.Address.Town)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Address.City)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address.City)
#Html.ValidationMessageFor(model => model.Address.City)
</div>
#*<div class="editor-label">
#Html.LabelFor(model => model.Address.County)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Address.CountyId, Model.Counties)
</div>*#
<div class="editor-label">
#Html.LabelFor(model => model.Address.PostalCode)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address.PostalCode)
#Html.ValidationMessageFor(model => model.Address.PostalCode)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Can anyone please offer any advice as to why my return ViewModel values are NULL when all fields are populated?
I've checked in Google Chrome browser using the Network Record feature and all values ARE posted back in JSON format.
Many thanks.
------------ EDIT ---------------
Here's part of what I can see from the Google Chrome Network Monitor
Company.Name:ABC123
Company.CreatedDate:2014/05/13 00:00:00
....
So it is definitely being returned.
I was able to reproduce your issue and was confused because I know that the default MVC Model Binder understands complex types. I stripped away most of the code and just tried to do it with the Company object, which still failed. I then noticed that in vmCompanyAddress that the name of the class was also the name of the property:
public class vmCompanyAddress
{
public StatelyTechAdmin.Models.Company Company { get; set; }
I changed the name of the property to something different from the class name and it started working:
public class vmCompanyAddress
{
public StatelyTechAdmin.Models.Company TheCompany { get; set; }
We had the same problem today. The accepted answer in this question is only a dirty workaround for the actual problem.
ClassName and PropertyName in a form model can be the same, there is no limitation in the model binder. The limitation is the parameter of the action in your controller. You must not name the parameter like a property with complex type in your form model. Cause the binder will try to bind the HTTP POST form value of company to this paramter in your controller. It will not work for you, cause the binder tries to bind the values of a Company Type to CompanyAddress type.
To fix your problem, you simply have to rename the parameter company to companyAddressModel - or anything which is not a property in your model class.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CompanyAddress company)
change to:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CompanyAddress companyAddressModel)
See here for more information about model binding: http://aspnetmvc.readthedocs.org/projects/mvc/en/latest/models/model-binding.html
MVC will try to bind request data to the action parameters by name.
MVC will look for values for each parameter using the parameter name
and the names of its public settable properties. [...] In addition to route values
MVC will bind data from various parts of the request and it does so in
a set order. Below is a list of the data sources in the order that
model binding looks through them:
Form values: These are form values that go in the HTTP request using the POST method.
Route values: The set of route values provided by routing.
Query strings: The query string part of the URI.
A good example from ASP.NET WebAPI documentation, which is using the same technique:
HttpResponseMessage Put(int id, Product item) { ... }
Here the Id property of Product is mapped to the id parameter in the controller. Which will work, cause in the action the same primitive data type is used as in the model class.
Have not tried this myself but had a lot of similar issues a long time ago that I solved with custom ModelBinder:s which I do not recommend.
I guess your data does not look like: { Company: {...}, Address: {...} }?
I think the solution is to have MVC to understand the structure of the data using templates and EditorFor(). See http://lostechies.com/jimmybogard/2011/09/07/building-forms-for-deep-view-model-graphs-in-asp-net-mvc/ for a good example!
Ensure your ViewModel is exposing properties and not just fields.
This works:
public DAL.Models.Account acct {get;set;}
This doesn't:
public DAL.Models.Account acct;
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)
I have a page with the same input box added a number of times.
#Html.TextBoxFor(m => m.Product)
#Html.TextBoxFor(m => m.Product)
#Html.TextBoxFor(m => m.Product)
How to I bind this to the Model.
I've tried:
public class Shop
{
public string ShopName { get; set; }
[Remote("ProductExists", "Account", AdditionalFields = "ShopName", ErrorMessage = "Product is already taken.")]
public List<String> Product { get; set; }
}
But I can only ever see the data in the first field. Also I tried:
#Html.TextBoxFor(m => m.Product[0])
#Html.TextBoxFor(m => m.Product[1])
#Html.TextBoxFor(m => m.Product[2])
But remote validation doesn't work so I'm a little stumped here. Essential what I would like to achieve is to send the list of products with the shop so that it can be validated via a remote call to a function. I tried putting the products within there own public class but then I wasn't able to access the shop name from within that class.
This is the Controller Action I'm trying to use:
public JsonResult ProductExists(List<String> Product, string ShopName)
Any Ideas how I could solve this would be so much appreciated?
EDIT
This Semi works but remote validation still isn't passing ShopName:
public class Shops
{
[Required]
public string ShopName { get; set; }
public List<Products> Product { get; set; }
}
public class Products
{
[Required]
[Remote("ProductExists", "Home", AdditionalFields = "ShopName", ErrorMessage = "Product is already taken.")]
public String Product { get; set; }
}
Controller Action:
public JsonResult ProductExists(List<String> Product, string ShopName)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
View:
#model Shop.Models.Shops
#{
ViewBag.Title = "Shop";
}
<h2>Shop</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Shop</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ShopName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ShopName)
#Html.ValidationMessageFor(model => model.ShopName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Product[0])
#Html.ValidationMessageFor(model => model.Product[0])
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Product[1])
#Html.ValidationMessageFor(model => model.Product[1])
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Product[2])
#Html.ValidationMessageFor(model => model.Product[2])
</div>
<input type="submit" value="Create" />
</fieldset>
}
look at the following answer. I would make product a class on its own like you tried. Loot at the rendered html code for the page and check out the field name for the ShopName textbox. I think it should be ShopName, if so you dont need to change the AdditionalFields attribute if not change it to the name rendered.
So something like this:
public class Shop
{
public string ShopName { get; set; }
public List<Products> Product { get; set; }
}
public class Products
{
[Remote("ProductExists", "Account", AdditionalFields = "ShopName", ErrorMessage = "Product is already taken.")]
public String Product { get; set; }
}
in your view do something like this:
foreach(var item in Model.products)
{
#Html.TextBoxFor(item => item.product) // not sure if the syntax is right
}
I'm trying my hardest to use ViewModels correctly in my web application, but I'm running into various problems. One of which, is if I set a breakpoint just after I post using a Create action, my viewModel hasn't stored any of my form values. I must be doing something wrong, but I've tried a few things. Including the code below, where I name the form items the same as the viewModel fields to see if that helps.
I'm also wondering what exactly properties in your viewmodel should represent. I've seen people use different things in blog posts and whatnot.
If the view is going to render a select list, I'm under the impression the viewmodel should hold an IEnumerable SelectListItem for this as below. Yet I've seen people use IEnumerable Entity instead, to represent the type the select list represents.
Can anybody shed some light on this for me? I scrapped my entire business logic last night so I could start a fresh and try and do it correctly.
My ViewModel:
public class ServerCreateViewModel
{
public int Id { get; set; }
// CompanyName represents a field in the Company model. I did this to see if
// it would help with model binding. Beforehand it was Companies to represent the type. I've done the same for the rest of them, so I wont comment on this again.
public IEnumerable<SelectListItem> CompanyName { get; set; }
// Represents the Game model.
public IEnumerable<SelectListItem> GameTitle { get; set; }
//Represents the Location model, etc...
public IEnumerable<SelectListItem> City { get; set; }
public IEnumerable<SelectListItem> NumberOfPlayers { get; set; }
public IEnumerable<SelectListItem> CurrencyAbbreviation { get; set; }
}
My Controller action:
public ActionResult Create()
{
var viewModel = new ServerCreateViewModel();
viewModel.CompanyName = new SelectList(_dataService.Companies.All(), "Id", "CompanyName");
viewModel.GameTitle = new SelectList(_dataService.Games.All(), "Id", "GameTitle");
viewModel.City = new SelectList(_dataService.Locations.All(), "Id", "City");
viewModel.NumberOfPlayers = new SelectList(_dataService.ServerPlayers.All(), "Id", "NumberOfPlayers");
return View(viewModel);
}
[HttpPost]
public ActionResult Create(FormCollection collection, ServerCreateViewModel viewModel)
{
try
{ // I put a breakpoint in here to check the viewModel values.
// If I dont pass the viewModel into the constructor, it doesnt exist.
// When I do pass it in, its empty.
return Content("Success");
}
catch
{
return Content("Fail");
}
}
My View:
#model GameserverCompare.ViewModels.Server.ServerCreateViewModel
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Server</legend>
#Html.HiddenFor(m => m.Id)
<div class="editor-label">
#Html.LabelFor(model => model.CompanyName)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => Model.CompanyName, Model.CompanyName)
#Html.ValidationMessageFor(model => model.CompanyName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.GameTitle)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => Model.GameTitle, Model.GameTitle)
#Html.ValidationMessageFor(model => model.GameTitle)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.City)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => Model.City, Model.City)
#Html.ValidationMessageFor(model => model.City)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.NumberOfPlayers)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => Model.NumberOfPlayers, Model.NumberOfPlayers)
#Html.ValidationMessageFor(model => model.NumberOfPlayers)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Since you're using SelectList properties in the form model, you will need to have a different model to represent the selected values in those lists:
public class ServerCreatePostbackModel
{
public int Id { get; set; }
// CompanyName represents a field in the Company model.
public string CompanyName { get; set; }
// Represents the Game model.
public string GameTitle { get; set; }
//Represents the Location model, etc...
public string City { get; set; }
public int NumberOfPlayers { get; set; }
public string CurrencyAbbreviation { get; set; }
}
Have your HttpPost action take one of these as its argument.
Oh, and be sure to use HiddenFor for the Id property, so it gets sent back with the other data.
How can i make this work like I have 5 fields in my database table .
I created a model for validation with datannotations and created the compare password field as well with comparepassword attribute. (now my model has 6 fields including one external field compare password and 5 database fields)
I created a view with that model.(User)
Now I created a controller as well but the problem arise here that when calling that ActionMethod the compiler complains about the external field and tells it cannot find any extension method. How can I create the extension method or solve this error?
[HttpPost]
public ActionResult Create(User Users)
{
}
This is the error I get:
CS1061: 'MvcApplication1.Models.User' does not contain a definition for 'ComparePassword' and no extension method 'ComparePassword' accepting a first argument of type 'MvcApplication1.Models.User' could be found (are you missing a using directive or an assembly reference?)
My Model:
[MetadataType(typeof(UserModel))]
public partial class User { }
public class UserModel
{
[Display(Name = "User Name")]
[Remote("Username", "User", ErrorMessage = "User Name already exists")]
[Required(ErrorMessage = "User Name is required")]
public string vcr_UserName { get; set; }
[RegularExpression(#"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Must be a valid Email Address")]
[Remote("EmailAddress", "User", ErrorMessage = "Email Address already exists")]
[Required(ErrorMessage = "Email is required")]
[Display(Name = "Email Address")]
public string vcr_EmailAddress { get; set; }
[Display(Name = "Password")]
[RegularExpression(#"^.{3,16}$", ErrorMessage = "The Password length must be between 3 and 16 characters ")]
[Required(ErrorMessage = "Password is required")]
public string vcr_Password { get; set; }
[Display(Name = "Compare Password")]
[Compare("vcr_Password", ErrorMessage = "Passwords do not match")]
public string ComparePassword { get; set; }
[Required(ErrorMessage = "Country is required")]
[Display(Name = "Country")]
public string vcr_Country { get; set; }
[Required(ErrorMessage = "Website is required")]
[Display(Name = "WebSite")]
public string vcr_Website { get; set; }
[Display(Name = "Expertise")]
[Required(ErrorMessage = "Expertise is required")]
public string vcr_Expertise { get; set; }
public int int_GroupId { get; set; }
public Boolean bit_Active { get; set; }
}
My Controller
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(User Users)
{
try
{
UserRepository UserRep = new UserRepository();
if (ModelState.IsValid)
{
Users.int_GroupId = 2;
Users.dtm_CreatedDate = DateTime.Now;
Users.bit_Active = true;
UserRep.Add(Users);
UserRep.Save();
}
return View();
}
catch { return View(); }
}
View
#model MvcApplication1.Models.User
{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
Index
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Users</legend>
<div class="editor-label">
#Html.LabelFor(model => model.vcr_UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.vcr_UserName)
#Html.ValidationMessageFor(model => model.vcr_UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.vcr_Password)
</div>
<div class="editor-field">
#Html.PasswordFor(model => model.vcr_Password)
#Html.ValidationMessageFor(model => model.vcr_Password)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ComparePassword)
</div>
<div class="editor-field">
#Html.PasswordFor(model => model.ComparePassword)
#Html.ValidationMessageFor(model => model.ComparePassword)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.vcr_EmailAddress)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.vcr_EmailAddress)
#Html.ValidationMessageFor(model => model.vcr_EmailAddress)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Ok when i click the create i am getting the above error
What do you mean by "external field"?
One thing that already comes to mind is:
Data annotations for view behaviour should not be placed on a model class.
You should separate your model facing the database from the viewmodel facing the view.
There are numerous articles about that.
If you create a viewmodel, you can add the 6th field there, add the data annotations, have the validation do its thing, etc.
You can use a tool like AutoMapper or ValueInjecter to perform the mapping from model to viewmodel and vice versa, so you don't have to write too much code.
If you have any further questions, feel free to ask...