MVC3 data-val-* attributes not emitted from model editor template - asp.net-mvc-3

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

Related

How to use CheckBoxFor in MVC forms with other form controls

Basically, i have a form with a textbox, radio button and a check box control. now i face problem with the checkbox control when i submit my page
I have a model like this
public class PersonDetails
{
public int personID { get; set; }
public string PersonName { get; set; }
public string Gender { get; set; }
public List<Education> Education { get; set; }
public string EmailID { get; set; }
public string Address { get; set; }
}
public class Education
{
public string Qualification { get; set; }
public bool Checked { get; set; }
public List<Education> GetQualification()
{
return new List<Education>{
new Education {Qualification="SSC",Checked=false},
new Education {Qualification="HSC",Checked=false},
new Education {Qualification="Graduation",Checked=false},
new Education {Qualification="PostGraduation",Checked=false}
};
}
}
and i have a view like this
#using (Html.BeginForm("GetDetails", "User", FormMethod.Post, new { id = "person-form" }))
{
<div class="col-xs-12">
<label>Person Name</label>
#Html.TextBoxFor(x => x.PersonName)
</div>
<div class="col-xs-12">
<label>Gender</label>
#Html.RadioButtonFor(x => x.Gender, "Male")
#Html.RadioButtonFor(x => x.Gender, "Female")
</div>
<div class="col-xs-12">
<label>Education</label>
#{
Html.RenderPartial("Qualification", new LearnAuthentication.Controllers.Education().GetQualification());
}
</div>
<div class="col-xs-12">
<input type="submit" value="Submit" />
</div>
}
and the partial view like this
#model List<LearnAuthentication.Controllers.Education>
<br />
#for (int i = 0; i < Model.Count(); i++)
{
#Html.HiddenFor(x => Model[i].Qualification)
#Html.CheckBoxFor(x => Model[i].Checked)
#Html.DisplayFor(x => Model[i].Qualification)
<br />
}
and my action method is this
[HttpPost]
public ActionResult GetDetails(PersonDetails personDetails)
{
return View();
}
now when i run my app i tend to get all the information but when i submit the page i get this property with null values
public List Education { get; set; }
can any of you guys help me on what i am doing wrong or could you direct me to the right path on how to achieve this.
Your use of a partial to generate the controls for Education is generating inputs such as
<input type="hidden" name="[0].Qualification" ... />
<input type="hidden" name="[1].Qualification" ... />
but in order to bind, they need to have name attributes which match your model
<input type="hidden" name="Education[0].Qualification" ... />
<input type="hidden" name="Education[1].Qualification" ... />
Rename you partial to Education.cshtml (to match the name of the class) and move it to your /Views/Shared/EditorTemplates folder (or /Views/yourControllerName/EditorTemplates if you want a specific template just for that controller)
Then change the partial to
#model LearnAuthentication.Controllers.Education
#Html.HiddenFor(m => m.Qualification)
#Html.LabelFor(m => m.Checked)
#Html.CheckBoxFor(m => m.Checked)
#Html.DisplayFor(m => m.Qualification)
and in the main view replace
<label>Education</label>
#{ Html.RenderPartial("Qualification", new LearnAuthentication.Controllers.Education().GetQualification()); }
with
<span>Education</span> // its not a label
#Html.EditorFor(m => m.Education)
which will correctly generate the correct html for each item in your collection
Side note: Other alternatives which would work would be to change the POST method signature to
[HttpPost]
public ActionResult GetDetails(PersonDetails personDetails List<Education> educationDetails)
or to pass the HtmlFieldPrefix to the partial as explained in getting the values from a nested complex object that is passed to a partial view

Pass Json data object from view containing partial view in MVC4

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.

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 Actionlink with submit

I am new MVC user and I am trying to make shopping cart as following MVC Music Store tutorial
I am trying to pass the radiobutton value which is different price types through actionlink.
Is it possible to pass the value with productId?
When I click the link, it will call 'AddToCart' method.
Could you help me? thanks.
Product model
namespace MvcApplication2.Models
{
public class Product
{
[Key] public int productId { get; set; }
public int categoryId { get; set; }
[Required(ErrorMessage = "Product model name is required")]
public String model { get; set; }
[DisplayFormat(DataFormatString = "{0:0.#}")]
public decimal displaySize { get; set; }
public String processor { get; set; }
public int ramSize { get; set; }
public int capacity { get; set; }
public String colour { get; set; }
public String description { get; set; }
public decimal price { get; set; }
public decimal threeDayPrice { get; set; }
public decimal aWeekPrice { get; set; }
public decimal twoWeekPrice { get; set; }
public decimal aMonthPrice { get; set; }
public decimal threeMonthPrice { get; set; }
public decimal sixMonthPrice { get; set; }
//public decimal sixMonthPrice { get { return price * 0.25M; } }
public int stock { get; set; }
public virtual Category Category { get; set; }
}
}
details.cshtml
#model MvcApplication2.Models.Product
<td>
Rental Period: <br />
#using (Html.BeginForm())
{
<div class="display-label">
#Html.RadioButtonFor(model => model.price, Model.threeDayPrice)
3 day: £#Model.threeDayPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, Model.aWeekPrice)
1 week: £#Model.aWeekPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.twoWeekPrice)
2 week: £#Model.twoWeekPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.twoWeekPrice)
1 month: £#Model.twoWeekPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.threeMonthPrice)
3 month: £#Model.threeMonthPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.sixMonthPrice)
6 month: £#Model.sixMonthPrice
</div>
}
</td>
</tr>
</table>
<p class="button" style="margin-left:200px; width:90px;">
//Is it possible to submit the selected radiobutton value through this?
#Html.ActionLink("Add to cart", "AddToCart", "ShoppingCart", new { id = Model.productId }, "")
</p>
---Added controller---
ShoppingCartController.cs
public ActionResult AddToCart(int id)
{
// Retrieve the product from the database
var addedProduct = db.Product
.Single(product => product.productId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduct);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
Just use a submit button instead of an ActionLink. This way all the input values will be sent to the controller when you submit the form:
#model MvcApplication2.Models.Product
<td>
Rental Period: <br />
#using (Html.BeginForm("AddToCart", "ShoppingCart", new { id = Model.productId }, FormMethod.Post))
{
<div class="display-label">
#Html.RadioButtonFor(model => model.price, Model.threeDayPrice)
3 day: £#Model.threeDayPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, Model.aWeekPrice)
1 week: £#Model.aWeekPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.twoWeekPrice)
2 week: £#Model.twoWeekPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.twoWeekPrice)
1 month: £#Model.twoWeekPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.threeMonthPrice)
3 month: £#Model.threeMonthPrice
</div>
<div class="display-label">
#Html.RadioButtonFor(model => model.price, #Model.sixMonthPrice)
6 month: £#Model.sixMonthPrice
</div>
<button type="submit">Add to cart</button>
}
</td>
Because you say you are new right off the bat I'm going to tell you that the way you are going about this is not the best way to achieve what you are trying to achieve.
Putting a submit button at the bottom of the form will get the data to post and bind to Product if you change the top of the form to
#using (Html.BeginForm("AddToCart", "WHATEVERYOURCONTROLLERISCALLED"))
but I think you are missing a few key points here.
There are some conventions that you seem to be ignoring
ShoppingCart.cs should be named ShoppingCartController.cs and appear in the controllers folder of your project
Instead of naming each price on the model you can use a list of prices options and display them on the form as a series of radio buttons while putting the mutually exclusive choice. for example.
The Model
public class Product{
// remove all the different price properties.
// other properties go here...And while you are at it Use Pascal case for property names Eg. displaySize would be DisplaySize but I guess that is up to you.
[Required]
public string PriceChoice { get; set; }
}
The Controller
public class ShoppingCartController : Controller
{
public ActionResult Details(int productId)
{
// get the product from the database
var model = Database.GetProductById(productId);
// set a default if you want
model.PriceChoice = "a";
return View(model);
}
[HttpPost]
public ActionResult AddToCart(Product model)
{
// do whatever you need to do
return RedirectToAction("Details", new { id = model.Id });
}
}
The View
#using (Html.BeginForm())
{
<div>A: #Html.RadioButtonFor(x => x.PriceChoice , "a")</div>
<div>B: #Html.RadioButtonFor(x => x.PriceChoice , "b")</div>
#Html.ValidationMessageFor(x => x.PriceChoice )
<input type="submit" value="OK" />
}
Now that's all very abridged and basic so I hope you get the gist of it.
Also you'll find some value in reading this Post Redirect Get So while it doesn't strictly apply to what you are doing it will explain the structure of the code you are reading in the examples where you see RedirectToAction.
Now if you want to do this really cleverly you will have to learn some javascript and issue an Ajax command.
Hope this helps

Getting the parent model ID when adding a child entry in MVC 3 w/razor?

So in a one to many relational database structured app, you of course need to be able to add multiple child entries for a parent... So let's say that you have a User, and the User can have one Profile, but each profile can have multiple Projects, and of course Projects consist of multiple child tables, such as for example, ProjectCodeSamples, being one of them...
So obviously to add a new ProjectCodeSample, it requires the ProjectID that it belongs to (as the foreign key)... So in the AddCodeSample View, how do you get that value, the value of the ProjectID, so that you can put it in a hidden field and pass it?
Here is the ProjectCodeSample Model:
namespace ProDevPortMVC3
{
using System;
using System.Collections.Generic;
public partial class ProjectCodeSample
{
public int ProjectCodeSampleID { get; set; }
public int ProjectID { get; set; }
public string ProjectCodeSampleContent { get; set; }
public string ProjectCodeSampleDescription { get; set; }
public virtual Project Project { get; set; }
}
}
Here are my two Controller Action Methods for the AddCodeSample:
//
// GET: /Project/AddCodeSample
public ActionResult AddCodeSample()
{
return View();
}
//
// POST: /Project/AddCodeSample
[HttpPost]
public ActionResult AddCodeSample(ProjectCodeSample projectcodesample)
{
projectcodesample.ProjectCodeSampleContent = projectcodesample.ProjectCodeSampleContent.TrimStart();
if (ModelState.IsValid)
{
db.ProjectCodeSamples.Add(projectcodesample);
db.SaveChanges();
return RedirectToAction("Details/" + projectcodesample.ProjectID);
}
else
{
return View(projectcodesample);
}
}
Here is my AddCodeSample View:
#model ProDevPortMVC3.ProjectCodeSample
#{
ViewBag.Title = "Add Code Sample";
}
<style type="text/css">
.editor-label { width: 200px; }
.editor-field { width: 700px; }
.submit-button-row { width: 900px; }
.bottom-nav { width: 900px; }
</style>
<h2>Add Code Sample</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 style="float: left; width: 900px;">
<legend>Project Code Sample</legend>
#Html.HiddenFor(model => model.ProjectID)
<div class="display-editor-label-field-row">
<div class="editor-label">
#Html.LabelFor(model => model.ProjectCodeSampleDescription, "Code Sample Description")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.ProjectCodeSampleDescription, 4, 85, null)
#Html.ValidationMessageFor(model => model.ProjectCodeSampleDescription)
</div>
</div>
<br />
<div class="display-editor-label-field-row">
<div class="editor-label">
#Html.LabelFor(model => model.ProjectCodeSampleContent, "Code Sample")
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.ProjectCodeSampleContent, 15, 85, null)
#Html.ValidationMessageFor(model => model.ProjectCodeSampleContent)
</div>
</div>
<br />
<div class="display-editor-label-field-row">
<div class="submit-button-row">
<input type="submit" value="Save" />
</div>
</div>
<br />
<div class="bottom-nav">
#Html.ActionLink("Cancel", "Details", new { id = ViewContext.RouteData.Values["ID"] })
</div>
</fieldset>
}
So obviously this will not work, because "#Html.HiddenFor(model => model.ProjectID)" will be empty... So what am I doing wrong, how do you get the Parent ID so that you can make Child entries?
You could pass the id from the previous page into this page using a querystring in your link:
public ActionResult AddCodeSample(int id)
{
var m = new ProjectCodeSample();
m.ProjectID = id;
return View(m);
}
So on your 'parent' project page, it could have a link like this:
Add Code Sample

Resources