Pass Json data object from view containing partial view in MVC4 - ajax

I am creating an MVC4 Form for person.
I have these Partial Views containing Information about Contact Info and Postal Address.
ContactInfo.cshtml
#model Demo.Models.ContactInfo
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<link rel="stylesheet" href="~/Content/plugins/validationengine/css/validationEngine.jquery.css" />
<h2>ContactInfo</h2>
<div class="form-group">
<label class="control-label col-lg-4">PhoneNumber</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.PhoneNumber)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">CellNumber</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.CellNumber)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">Email</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.Email)
</div>
</div>
PostalAddress.cshtml
#model Demo.Models.PostalAddress
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<link rel="stylesheet" href="~/Content/plugins/validationengine/css/validationEngine.jquery.css" />
<h2>PostalAddress</h2>
<div class="form-group">
<label class="control-label col-lg-4">CountryID</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.CountryID)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">CityID</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.CityID)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">ProvinceID</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.ProvinceID)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">ZipCode</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.ZipCode)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">StreetAddress</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.StreetAddress)
</div>
</div>
Here are the Model classes for Person,Postal Address and Contact Info.
ContactInfo.cs
using System;
using System.Collections.Generic;
namespace Demo.Models
{
public partial class ContactInfo
{
public ContactInfo()
{
this.Branches = new List<Branch>();
this.People = new List<Person>();
}
public long ID { get; set; }
public Nullable<int> PhoneNumber { get; set; }
public Nullable<int> CellNumber { get; set; }
public string Email { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
public virtual ICollection<Person> People { get; set; }
}
}
Here is the Person.cs
using System;
using System.Collections.Generic;
namespace Demo.Models
{
public partial class Person
{
public Person()
{
this.Branches = new List<Branch>();
this.Documents = new List<Document>();
this.Faculties = new List<Faculty>();
this.Institutes = new List<Institute>();
this.Parents = new List<Parent>();
this.Students = new List<Student>();
this.StudentParents = new List<StudentParent>();
this.StudentParents1 = new List<StudentParent>();
}
public long ID { get; set; }
public string Name { get; set; }
public Nullable<bool> Gender { get; set; }
public Nullable<System.DateTime> DOB { get; set; }
public string Photo { get; set; }
public Nullable<long> ContactID { get; set; }
public Nullable<byte> PersonTypeID { get; set; }
public Nullable<long> PostalAddressID { get; set; }
public Nullable<byte> ReligionID { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
public virtual ContactInfo ContactInfo { get; set; }
public virtual ICollection<Document> Documents { get; set; }
public virtual ICollection<Faculty> Faculties { get; set; }
public virtual ICollection<Institute> Institutes { get; set; }
public virtual ICollection<Parent> Parents { get; set; }
public virtual PersonType PersonType { get; set; }
public virtual PostalAddress PostalAddress { get; set; }
public virtual Religion Religion { get; set; }
public virtual ICollection<Student> Students { get; set; }
public virtual ICollection<StudentParent> StudentParents { get; set; }
public virtual ICollection<StudentParent> StudentParents1 { get; set; }
}
}
PostalAddress.cs
using System;
using System.Collections.Generic;
namespace Demo.Models
{
public partial class PostalAddress
{
public PostalAddress()
{
this.Branches = new List<Branch>();
this.Papers = new List<Paper>();
this.People = new List<Person>();
}
public long ID { get; set; }
public Nullable<byte> CountryID { get; set; }
public Nullable<int> CityID { get; set; }
public Nullable<int> ProvinceID { get; set; }
public string ZipCode { get; set; }
public string StreetAddress { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
public virtual city city { get; set; }
public virtual country country { get; set; }
public virtual ICollection<Paper> Papers { get; set; }
public virtual ICollection<Person> People { get; set; }
public virtual province province { get; set; }
}
}
Here is the Main Person.cshtml
I am rendering the upper partial views in it and sending the json object data back.
#model Demo.Models.Person
#{
ViewBag.Title = "Person";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<legend>Person</legend>
<div class="form-group">
<label class="control-label col-lg-4">Name</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.Name)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">Gender</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.Gender)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">DOB</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.DOB)
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-4">Photo</label>
<div class="col-lg-4">
#Html.EditorFor(model => model.Photo)
</div>
</div>
#Html.Partial("ContactInfo", new Demo.Models.ContactInfo())
<div class="form-group">
<label class="control-label col-lg-4">PersonTypeID</label>
<div class="col-lg-4">
#Html.DropDownList("PersonTypeID", String.Empty)
</div>
</div>
#Html.Partial("PostalAddress", new Demo.Models.PostalAddress())
<div class="form-group">
<label class="control-label col-lg-4">ReligionID</label>
<div class="col-lg-4">
#Html.DropDownList("ReligionID", String.Empty)
</div>
</div>
<p>
<input id="submit" class="submit" type="submit" value="Create" />
</p>
}
<script>
$('#submit').click(function (e) {
e.preventDefault();
//alert('hello');
var person = {
Name: $('#Name').val(),
Gender: $('#Gender').val(),
DOB: $('#DOB').val(),
Photo: $('#Photo').val(),
PersonTypeID: $('PersonTypeID').val(),
ContactInfo: {
PhoneNumber: $('#PhoneNumber').val(),
CellNumber: $('#CellNumber').val(),
Email: $('#Email').val()
},
PostalAddress: {
CountryID: $('#CountryID').val(),
CityID: $('#CityID').val(),
ProvinceID: $('#ProvinceID').val(),
ZipCode: $('#ZipCode').val(),
StreetAddress: $('#StreetAddress').val(),
},
};
var data = { jsonperson: person };
//console.log(data);
$.ajax({
url: '/Person/Create',
type: "post",
data: JSON.stringify(data),
success: function () {
$('#message').html('person added').fadeIn();
},
error: function () {
$('#message').html('person added').fadeIn();
}
});
But when i send the data from form to controller The data containing postal address and Contact info is Null.
Here is the Person Controller
[HttpPost]
public JsonResult Create(Person jsonperson)
{
if (ModelState.IsValid)
{
db.People.Add(jsonperson);
db.SaveChanges();
// return RedirectToAction("Index");
}
ViewBag.ContactID = new SelectList(db.ContactInfoes, "ID", "Email", jsonperson.ContactID);
ViewBag.PersonTypeID = new SelectList(db.PersonTypes, "ID", "Name", jsonperson.PersonTypeID);
ViewBag.PostalAddressID = new SelectList(db.PostalAddresses, "ID", "ZipCode", jsonperson.PostalAddressID);
ViewBag.ReligionID = new SelectList(db.Religions, "ID", "Name", jsonperson.ReligionID);
// return View(jsonperson);
JsonResult jr = new JsonResult();
jr.Data = true;
return jr;
}
Data is coming to the controller but Contact Info details and Postal Address is null. It is driving me crazy .
Thanks in advance.

the serialized JSON data that is being passed to your controller after you submit the form, does not have any property such as ContactId or PersonTypeID etc
your controller will receive PhoneNumber, CellNumber, Email, CountryID, CityID, ProvinceID, ZipCode, StreetAddress
therefore your model Person should have the above properties as it is named in your partial view models so they can be read accordingly into your Person model.

Related

How to bind dropdown list from action method in MVC 3 inside create view

I want to populate a dropdownlist on create view with form also. Here is my code
#model CM.Models.TVSerialEpisode
#{
ViewBag.Title = "AddEpisode";
}
#Html.Action("ListAllSeason","TvSerial") //here i want to call this action method so i could bind all tv serial
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>TVSerialEpisode</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Serial_ID)
</div>
<div class="editor-field">
#Html.DropDownList("Serial_ID", new List<SelectListItem>
{
new SelectListItem { Text = "Backstrom", Value="16" },
new SelectListItem{Text="10 Things I hate about You", Value="15"},
new SelectListItem { Text = "Castle", Value="14" }
}, "Select Serial")
#Html.ValidationMessageFor(model => model.Serial_ID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Episode_No)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Episode_No)
#Html.ValidationMessageFor(model => model.Episode_No)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Episode_Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Episode_Name)
#Html.ValidationMessageFor(model => model.Episode_Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.File_Url_480p)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.File_Url_480p)
#Html.ValidationMessageFor(model => model.File_Url_480p)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.File_Url_720p)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.File_Url_720p)
#Html.ValidationMessageFor(model => model.File_Url_720p)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Is_Active)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Is_Active)
#Html.ValidationMessageFor(model => model.Is_Active)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
here is the model class
namespace CM.Models
{
[Table("tbltvserial")]
public class TVSerial
{
[Key]
public Int64 Serial_ID { get; set; }
public string Serial_Name { get; set; }
public string Season_Name { get; set; }
public int Season_No { get; set; }
public int? Release_Year { get; set; }
}
public class TVSerial_VM
{
public Int64 Serial_ID { get; set; }
public string Serial_Name { get; set; }
public int Season_No { get; set; }
}
[Table("tblserialepisode")]
public class TVSerialEpisode
{
[Key]
public Int64 Video_ID { get; set; }
public Int64 Serial_ID { get; set; }
public int Episode_No { get; set; }
public string Episode_Name { get; set; }
public string File_Url_480p { get; set; }
public string File_Url_720p { get; set; }
public string Description { get; set; }
public bool Is_Active { get; set; }
public DateTime Uploaded_Time { get; set; }
}
public class TvSerialContext : DbContext
{
public DbSet<TVSerialEpisode> TvSerialEpisodes { get; set; }
public DbSet<TVSerial> TvSerials { get; set; }
}
}
here are controller class
public class TvSerialController : Controller
{
public List<TVSerial_VM> ListAllSeason()
{
try
{
TvSerialContext tvContext = new TvSerialContext();
List<TVSerial_VM> tv = tvContext.TvSerials
.Select(t => new TVSerial_VM
{
Serial_Name = t.Serial_Name,
Season_No=t.Season_No,
Serial_ID=t.Serial_ID
}).OrderBy(t=> t.Season_Name).
ToList();
return (tv);
}
catch (Exception ex)
{
return null;
}
}
}
public class TvSerialEpisodeController : Controller
{
TvSerialContext tvContext = new TvSerialContext();
public ActionResult AddEpisode()
{
return View();
}
[HttpPost]
public ActionResult AddEpisode(TVSerialEpisode tvEpisode)
{
if (ModelState.IsValid)
{
tvContext.TvSerialEpisodes.Add(tvEpisode);
tvContext.SaveChanges();
return RedirectToAction("AddEpisode");
}
return View(tvEpisode);
}
}
I don't know how to bind the tvserial list inside above view page. basically i want to choose the serial id from dropdown list, is this posible to call a action method inside the create view.
To populate your SelectList from the database, in the controllers AddEpisode() method use
ViewBag.SerialList = db.TvSerials.ToList().Select(x => new SelectListItem(){ Value = x.Serial_ID.ToString(), Text = x.Serial_Name });
and then in the view use
#Html.DropDownListFor(m => m.Serial_ID, (IEnumerable<SelectListItem>)ViewBag.SerialList, "Select Serial")
although it is recommended you use a view model and include a IEnumerable<SelectListItem> SerialList property in the view model so that it is
#Html.DropDownListFor(m => m.Serial_ID, Model.SerialList, "Select Serial")

"Null" Foreign key relationship creating record on MVC3 + EF

I'm using EF + MVC3 + razor
I have my userProfile model class with a Name, Surname variables + a foreign key Hobby (as I want to see it as a dropdown)
I created a controler simply selecting this clase and Data Context.
When I try to create the record, it doesn’t let me, as it says in the validation area: "The Hobby field is required. " .
I want the "Hobby" dropdown not to be required.
How can I acomplish that?!..
This is what I have:
Model:
public class UserProfile {
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Surname { get; set; }
public int HobbiesId { get; set; }
public virtual Hobby Hobby { get; set; }}
public class Hobby
{
public int HobbiesId { get; set; }
public string HobbieName { get; set; }
public virtual ICollection<UserProfile> UserProfiles { get; set; }
}
public class UserProfileDBContext : DbContext
{
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Hobby> Hobbies{ get; set; }
}
View:
[..]#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>UserProfile</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Surname)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Surname)
#Html.ValidationMessageFor(model => model.Surname)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyId, "Hobby")
</div>
<div class="editor-field">
#Html.DropDownList("HobbyId", String.Empty)
#Html.ValidationMessageFor(model => model.HobbyIdId)
</div>
[..]
The controller's create is:
[HttpPost]
public ActionResult Create(UserProfile userprofile)
{
if (ModelState.IsValid)
{
db.UserProfiles.Add(userprofile);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.HobbyId = new SelectList(db.Hobbies, "HobbyId", "Hobby", userprofile.HobbyId);
return View(userprofile); }
I already tried modifying:
public class Hobby
{
public int ?HobbiesId { get; set; }
but it didn't work.
Any help?..
Thanks in advance!..
PnP
Add a foreign key constraint as shown below:
public int? HobbiesId { get; set; }
[ForeignKey("HobbiesId")]

can not add data from dropdown to table

I am using nhibernate and mvc3 in asp.net
I'm trying to add data into table where my table schema is like this:
public class HobbyMasters
{
[Key]
public virtual int HobbyId { get; set; }
[Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "NameRequired")]
public virtual string HobbyName { get; set; }
public virtual HobbyTypes HobbyType { get; set; }
[Required]
public virtual string HobbyDetails { get; set; }
[Required]
public virtual ICollection<HobbyMasters> HobbyNames { get; set; }
}
public class HobbyTypes
{
[Key]
public virtual int HobbyTypeId { get; set; }
[Required]
public virtual string HobbyType { get; set; }
public virtual ICollection<HobbyTypes> Hobby { get; set; }
}
in my Controller
public ActionResult Create()
{
ViewBag.c1 = (ICollection<HobbyTypes>)(new Hobby_MasterService().GetAllHobbyTypes());
return View();
}
//
// POST: /Hobbies/Create
[HttpPost]
public ActionResult Create(HobbyMasters hobby)
{
ViewBag.c1 = (ICollection<HobbyTypes>)new Hobby_MasterService().GetAllHobbyTypes();
try
{
if (ModelState.IsValid)
{
new Hobby_MasterService().SaveOrUpdateHobby(hobby);
return RedirectToAction("Index");
}
}
}
in the view:
#using (Html.BeginForm("Create", "Hobbies", FormMethod.Post))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Hobby Master</legend>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.HobbyName)
#Html.ValidationMessageFor(model => model.HobbyName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyType)
</div>
<div class="Editor-field">
#Html.DropDownListFor(model =>model.HobbyType.HobbyTypeId, new SelectList(ViewBag.c1, "HobbyTypeId", "HobbyType"), "-- Select --")
#Html.ValidationMessageFor(model => model.HobbyType)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyDetails)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.HobbyDetails)
#Html.ValidationMessageFor(model => model.HobbyDetails)
</div>
</fieldset>
<p><input type="Submit" value="Create" /> </p>
}
Apparently i found that My Modelstate.IsValid is always false.....
since it stores only the HobbyId and getting Hobby Type as null the HobbyMasters hobbytype object.....
dnt knw where i'm going wrong may be in dropdownlist or something else.....
Plaese help me asap:(
There are a couple of issues with your code:
First is the fact that you decorated HobbyNames collection property with the [Required] attribute. You should use this attribute only on simple properties. In fact you could leave the property but it will have absolutely no effect
The second issue with your code is that you have decorated the HobbyType string property of the HobbyTypes model with a [Required] attribute but you never use this property in your view. So no value is sent when you submit the form and your model is invalid.
Another issue with your code is that you bound the dropdown list to the model => model.HobbyType.HobbyTypeId property. But the HobbyTypeId is not a nullable type. And yet you made your dropdown contain a default value: "-- Select --". This is not possible. If you want to have a dropdown list with an optional value you must bind it to a nullable property on your model.
I have tried to clean up your code a little.
Model:
public class HobbyMasters
{
public virtual int HobbyId { get; set; }
[Required]
public virtual string HobbyName { get; set; }
public virtual HobbyTypes HobbyType { get; set; }
[Required]
public virtual string HobbyDetails { get; set; }
public virtual ICollection<HobbyMasters> HobbyNames { get; set; }
}
public class HobbyTypes
{
[Required]
public virtual int? HobbyTypeId { get; set; }
public virtual string HobbyType { get; set; }
public virtual ICollection<HobbyTypes> Hobby { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Create()
{
ViewBag.c1 = (ICollection<HobbyTypes>)(new Hobby_MasterService().GetAllHobbyTypes());
var model = new HobbyMasters();
return View(model);
}
//
// POST: /Hobbies/Create
[HttpPost]
public ActionResult Create(HobbyMasters hobby)
{
if (ModelState.IsValid)
{
try
{
new Hobby_MasterService().SaveOrUpdateHobby(hobby);
return RedirectToAction("Index");
}
catch (Exception ex)
{
ModelState.AddModelError("", ex.Message);
}
}
ViewBag.c1 = (ICollection<HobbyTypes>)new Hobby_MasterService().GetAllHobbyTypes();
return View(hobby);
}
}
View:
#model HobbyMasters
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Hobby Master</legend>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.HobbyName)
#Html.ValidationMessageFor(model => model.HobbyName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyType)
</div>
<div class="Editor-field">
#Html.DropDownListFor(model => model.HobbyType.HobbyTypeId, new SelectList(ViewBag.c1, "HobbyTypeId", "HobbyType"), "-- Select --")
#Html.ValidationMessageFor(model => model.HobbyType.HobbyTypeId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HobbyDetails)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.HobbyDetails)
#Html.ValidationMessageFor(model => model.HobbyDetails)
</div>
</fieldset>
<p><input type="Submit" value="Create" /></p>
}
Also I would very strongly recommend you to use view models. Don't pass your domain entities to your views. Define view models.

MVC3 data-val-* attributes not emitted from model editor template

I have created an editor template for one of my models in my current MVC3 project. This model is calling the correct editors for the properties of the underlying mode, but they're missing the unobtrusive data-val-* attributes for validation.
How can I get MVC to emit the data-val attributes?
Here's my model
[MetadataType(typeof(FieldTripRouteMetadata))]
public partial class FieldTripRoute
{
private class FieldTripRouteMetadata
{
[Required]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime Date { get; set; }
[Required]
[DisplayName("Route")]
public int RouteID { get; set; }
[Required]
[DisplayName("Departure Time")]
[UIHint("TimeWithPeriod")]
[DisplayFormat(DataFormatString = "{0:h:mm tt}")]
public DateTime DepartureTime { get; set; }
[Required]
[StringLength(255)]
[DisplayName("Pickup Location")]
public String PickupLocation { get; set; }
[Required]
[StringLength(255)]
public String Destination { get; set; }
[Required]
[DisplayName("Arrival Time")]
[UIHint("TimeWithPeriod")]
[DisplayFormat(DataFormatString = "{0:h:mm t}")]
public DateTime ArrivalTime { get; set; }
public bool IsReturnRoute { get; set; }
public int FieldTripID { get; set; }
}
and my Editor Template:
#model FieldTripRoute
#{string routeType = (Model.IsReturnRoute ? "return" : "");}
<fieldset class="add#(routeType)Route" style="clear: both; width: 620px; margin-right: auto; margin-left: auto;">
<legend>Add Route</legend>
<div style="float: left; width: 275px;">
<div>
<div class="editor-label">#Html.LabelFor(model => model.Date)</div>
<div class="editor-field">#Html.EditorFor(model => model.Date)</div>
<div class="validation-error">#Html.ValidationMessageFor(model => model.Date)</div>
</div>
<div>
<div class="editor-label">#Html.LabelFor(model => model.DepartureTime)</div>
<div class="editor-field">#Html.EditorFor(model => model.DepartureTime)</div>
<div class="validation-error">#Html.ValidationMessageFor(model => model.DepartureTime)</div>
</div>
<div>
<div class="editor-label">#Html.LabelFor(model => model.ArrivalTime)</div>
<div class="editor-field">#Html.EditorFor(model => model.ArrivalTime)</div>
<div class="validation-error">#Html.ValidationMessageFor(model => model.ArrivalTime)</div>
</div>
</div>
<div style="float: left;">
<div>
<div class="editor-label">#Html.LabelFor(model => model.RouteID)</div>
<div class="editor-field">#Html.DropDownListFor(model => model.RouteID, Model.EditRouteList)</div>
<div class="validation-error">#Html.ValidationMessageFor(model => model.RouteID)</div>
</div>
<div>
<div class="editor-label">#Html.LabelFor(model => model.PickupLocation)</div>
<div class="editor-field">#Html.TextBoxFor(model => model.PickupLocation)</div>
<div class="validation-error">#Html.ValidationMessageFor(model => model.PickupLocation)</div>
</div>
<div>
<div class="editor-label">#Html.LabelFor(model => model.Destination)</div>
<div class="editor-field">#Html.EditorFor(model => model.Destination)</div>
<div class="validation-error">#Html.ValidationMessageFor(model => model.Destination)</div>
</div>
</div>
<div style="clear: both; width: 100px; margin: 20px auto 0 auto;">
<input type="button" id="submit#(routeType)Form" name="submit#(routeType)Form" value="Add" />
</div>
</fieldset>
And my viewModel:
public class FieldTripEditViewModel
{
public FieldTrip Trip { get; set; }
public FieldTripRoute Route { get; set; }
public FieldTripRoute ReturnRoute { get; set; }
public FieldTripEditViewModel(){}
public FieldTripEditViewModel(FieldTrip trip)
{
this.Trip = trip;
this.Route = new FieldTripRoute();
this.ReturnRoute = new FieldTripRoute {IsReturnRoute = true};
}
}
I looked at this post and all of my base editor templates correspond to the idea of leaving the name as an empty string to allow MVC to generate it. Yet I still have no validation.
I was able to get it to function by adding a form tag before and after my editor template and adding this.ViewContext.FormContext = new FormContext();
at the beginning of the Editor Template.
It appears that when the control is passed to the editor template it loses the current form context. I tried just addin the ViewContext.FormContext command but without the addition of the form tags the embedded model would not validate.
So right now I have a form inside of a form and it works as intended, but it seems like there should be an easier way.
The idea for the formContext command came from here

How to bind a nested model in MVC3?

I've been reading all about UpdateModel() and custom model binders and i still cant figure this out. Seems like theres gotta be a simple answer to this.
I have a class called user that i user all over my MVC Web app.
public class User
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
[Email]
public string Email { get; set; }
[Required]
public string Password { get; set; }
public virtual ICollection<User> WorkTasks { get; set; }
}
And then a WorkTask that has it in a few places:
public class WorkTask
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
public DateTime? DesiredStartDate { get; set; }
public DateTime? DesiredEndDate { get; set; }
public TimeSpan? DesiredTimeSpent { get; set; }
public virtual ICollection<WorkTaskTag> Tags { get; set; }
public virtual ICollection<WorkTaskPeriod> Periods { get; set; }
public virtual ICollection<User> InvolvedUsers { get; set; }
public virtual User CreatedBy { get; set; }
public virtual User AssignedTo { get; set; }
public string UserNameAssignedTo
{
get
{
if(AssignedTo!=null)
return AssignedTo.Name;
return CreatedBy.Name;
}
}
public string TotalTimeSpent {
get
{
var concretePeriods = Periods
.Where(i => i.StartDate.HasValue && i.EndDate.HasValue);
if (concretePeriods != null && concretePeriods.Count() > 0)
{
TimeSpan ts = new TimeSpan();
foreach (var p in concretePeriods)
{
var t=p.EndDate.Value-p.StartDate.Value;
ts.Add(t);
}
TimePeriodHelpers help = new TimePeriodHelpers();
return help.GetTimeFormat(ts);
}
return "0:00";
}
}
}
So how do i make a create template for this WorkTask that allows the User class to be bound to the WorkTask in multiple places?
Here's my very shoddy attempt:
[HttpPost]
public ActionResult Create(WorkTask worktask)
{
LoadUsers();
string assignedto=Request["AssignedTo"];
var user = db.Users.First(i => SqlFunctions.StringConvert((double)i.ID) == assignedto);
UpdateModel<User>(user);
if (ModelState.IsValid)
{
db.WorkTasks.Add(worktask);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(worktask);
}
and the view:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DesiredStartDate,"Desired Start Date")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DesiredStartDate)
#Html.ValidationMessageFor(model => model.DesiredStartDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DesiredEndDate,"Desired End Date")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DesiredEndDate)
#Html.ValidationMessageFor(model => model.DesiredEndDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DesiredTimeSpent,"Desired Time Spent")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DesiredTimeSpent)
#Html.ValidationMessageFor(model => model.DesiredTimeSpent)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AssignedTo,"User Assigned To")
</div>
<div class="editor-field">
#Html.DropDownListFor(i=>Model.AssignedTo,(IEnumerable<SelectListItem>)ViewBag.Users)
#Html.ValidationMessageFor(model => model.AssignedTo)
</div>
<p>
<input type="submit" value="Create" />
</p>
Instead of trying to bind the nested User object, i made the form and controller based upon a ViewModel which just had the UserID. I then assumed that if the ViewModel validated correctly, than i can go ahead and persist the WorkTask and nested User objects.

Resources