I have model
public class QuestionViewModel
{
public string Text { get; set; }
public int Id { get; set; }
public bool IsMultiSelected { get; set; }
public IEnumerable<RadioButtonViewModel> AnswerViewModels { get; set; }
}
public class RadioButtonViewModel
{
public string Value { get; set; }
public string Name { get; set; }
}
And test controller
[HttpGet]
public ActionResult ProcessAnswers()
{
var question1 = new List<RadioButtonViewModel>
{
new RadioButtonViewModel
{
Value = "1",
Name = "Radio 1 option 1"
},
new RadioButtonViewModel
{
Value = "2",
Name = "Radio 1 option 2"
},
new RadioButtonViewModel
{
Value = "3",
Name = "Radio 1 option 3"
}
};
var question2 = new List<RadioButtonViewModel>
{
new RadioButtonViewModel
{
Value = "1",
Name = "Radio 2 option 1"
},
new RadioButtonViewModel
{
Value = "2",
Name = "Radio 2 option 2"
},
new RadioButtonViewModel
{
Value = "3",
Name = "Radio 2 option 3"
}
};
var qs = new List<QuestionViewModel>
{
new QuestionViewModel
{
Id = 1,
Text = "Please select correct variant in question 1",
AnswerViewModels = question1
},
new QuestionViewModel
{
Id = 2,
Text = "Please select correct variant in question 2",
AnswerViewModels = question2
}
};
return View("TestRadioView", qs);
}
[HttpPost]
public ActionResult ProcessAnswers(List<QuestionViewModel> answers)
{
return RedirectToAction("Index");
}
My View
#using System.Web.Mvc.Html
#using ExpertApplication.ViewModels
#model List<QuestionViewModel>
#{
ViewBag.Title = "Test Radio Button View";
}
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
</head>
<body>
<div>
#if(Model != null)
{
<br />
using(#Html.BeginForm("ProcessAnswers", "Home", FormMethod.Post))
{
foreach(var question in Model)
{
<h2>#question.Text</h2>
<br />
foreach(var radioButtonViewModel in question.AnswerViewModels)
{
#Html.RadioButton(question.Id.ToString(), radioButtonViewModel.Value)
#Html.Label(question.Id.ToString(), radioButtonViewModel.Name)
<br />
}
}
<input type="submit" value="Send" />
}
}
</div>
</body>
</html>
UPDATE
I change my view and model but i don't have correct answers
public IList<RadioButtonViewModel> AnswerViewModels { get; set; }
#using System.Web.Mvc.Html
#using ExpertApplication.ViewModels
#model List<QuestionViewModel>
#{
ViewBag.Title = "Test Radio Button View";
}
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
</head>
<body>
<div>
#if(Model != null)
{
if(ViewData["Message"] != null)
{
<h1>#ViewData["Message"]</h1>
}
else
{
<h1>Please answer the questions</h1>
}
<br />
using(#Html.BeginForm("ProcessAnswers", "Home", FormMethod.Post))
{
for(int i = 0; i < Model.Count(); i++)
{
var question = Model[i];
<h2>#question.Text</h2>
<br />
for(int j = 0; j < question.AnswerViewModels.Count(); j++)
{
var radioButtonViewModel = question.AnswerViewModels[j];
#Html.RadioButton(string.Format("QuestionViewModel[{0}].AnswerViewModels.Id", question.Id), radioButtonViewModel.Value)
#Html.Label(string.Format("{0}", question.Id), radioButtonViewModel.Name)
<br />
}
}
<input type="submit" value="Send" />
}
}
</div>
</body>
</html>
In action ProcessAnswers variable List answers is null.
Where is my trouble ?
The model binder can not create a type of IEnumerable so you will have to change it to a List or Collection
Related
I wanna send checkboxes value from View to Action with viewmodel.
Can you help me ؟
I'm sorry about my terrible English
You could try this way to achieve your requirements
View Model:
public class CheckBoxViewModel
{
public List<Plans> plans { get; set; }
}
public class Plans
{
public int PlanId { get; set; }
public string PlanName { get; set; }
public bool IsSelected { get; set; }
}
Controller When Load View Model:
public IActionResult LoadCheckBoxFromViewModel()
{
var plan = new List<Plans>()
{
new Plans(){ PlanName = "Plan A",PlanId =1, IsSelected= false},
new Plans(){ PlanName = "Plan B",PlanId =2, IsSelected= false},
new Plans(){ PlanName = "Plan C",PlanId =3, IsSelected= false},
new Plans(){ PlanName = "Plan D",PlanId =4, IsSelected= false}
};
var model = new CheckBoxViewModel();
model.plans = plan;
return View(model);
}
Note: I have loaded the checkbox with few predefined value to check. If you need a single checkbox so you can simply customize it as per your requirement. In that case you don't need to loop through the plan checkbox list.
View Of LoadCheckBoxFromViewModel Controller:
#model CheckBoxViewModel
#{
ViewData["Title"] = "LoadCheckBoxFromViewModel";
}
<h4>Load CheckBox From ViewModel</h4>
<h4>Submit value to Controller</h4>
<hr />
#using (Html.BeginForm("GetValueFromCheckBoxUsingViewModel", "StackOverFlow"))
{
for (int i = 0; i < Model.plans.Count; i++)
{
#Html.CheckBoxFor(r => Model.plans[i].IsSelected)
<label> #Model.plans[i].PlanName</label>
#Html.HiddenFor(h => #Model.plans[i].PlanId)
#Html.HiddenFor(h => #Model.plans[i].PlanName)
}
<input id="Button" type="submit" value="Save" class="btn btn-primary" />
}
Controller When Submit Checkbox:
[HttpPost]
public IActionResult GetValueFromCheckBoxUsingViewModel(CheckBoxViewModel checkBoxViewModel)
{
return View(checkBoxViewModel);
}
Output:
Hope it would guide you through.
It's supposed to validate and then go to the next view. However, it skips validation entirely and instead reloads the page. I think the issue is with the button itself on the view, I have also tried changing the anchor tag to a submit button, but that just brings me back to the index page. Any help would be appreciated.
My Controller
namespace Trip_Log.Controllers
{
public class TripController : Controller
{
private TripLogContext context { get; set; }
public TripController(TripLogContext ctx) => context = ctx;
public RedirectToActionResult Cancel()
{
TempData.Clear();
return RedirectToAction("Index", "Home");
}
[HttpGet]
public IActionResult Add(string id = "")
{
var vm = new TripViewModel();
if (id == "page2")
{
var accomodation = TempData[nameof(Trip.Accommodation)]?.ToString();
if (string.IsNullOrEmpty(accomodation))
{
vm.PageNumber = 3;
var destination = TempData[nameof(Trip.Destination)].ToString();
vm.Trip = new Trip { Destination = destination };
return View("Add3", vm);
}
else
{
vm.PageNumber = 2;
vm.Trip = new Trip { Accommodation = accomodation };
TempData.Keep(nameof(Trip.Accommodation));
return View("Add2", vm);
}
}
else if (id == "page3")
{
vm.PageNumber = 3;
vm.Trip = new Trip { Destination = TempData.Peek(nameof(Trip.Destination)).ToString() };
return View("Add3", vm);
}
else
{
vm.PageNumber = 1;
return View("Add1", vm);
}
}
[HttpPost]
public IActionResult Add(TripViewModel vm)
{
if(vm.PageNumber == 1)
{
if (ModelState.IsValid)
{
TempData[nameof(Trip.Destination)] = vm.Trip.Destination;
TempData[nameof(Trip.Accommodation)] = vm.Trip.Accommodation;
TempData[nameof(Trip.StartDate)] = vm.Trip.StartDate;
TempData[nameof(Trip.EndDate)] = vm.Trip.EndDate;
return RedirectToAction("Add", new { id = "page2" });
}
else
{
return View("Add1", vm);
}
}
else if(vm.PageNumber == 2)
{
TempData[nameof(Trip.AccommodationPhone)] = vm.Trip.AccommodationPhone;
TempData[nameof(Trip.AccommodationEmail)] = vm.Trip.AccommodationEmail;
return RedirectToAction("Add", new { id = "page3" });
}
else if(vm.PageNumber == 3)
{
vm.Trip.Destination = TempData[nameof(Trip.Destination)].ToString();
vm.Trip.Accommodation = TempData[nameof(Trip.Accommodation)].ToString();
vm.Trip.StartDate = (DateTime)TempData[nameof(Trip.StartDate)];
vm.Trip.EndDate = (DateTime)TempData[nameof(Trip.EndDate)];
vm.Trip.AccommodationPhone = TempData[nameof(Trip.AccommodationPhone)].ToString();
vm.Trip.AccommodationEmail = TempData[nameof(Trip.AccommodationEmail)].ToString();
context.Trips.Add(vm.Trip);
context.SaveChanges();
TempData["message"] = $"Trip to {vm.Trip.Destination} added";
return RedirectToAction("Index", "Home");
}
else
{
return RedirectToAction("Index", "Home");
}
}
}
}
My view
#model TripViewModel
#*
*#
#{
}
<h4>Add Trip Destination and Dates</h4>
<form asp-action="Add" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Trip.Destination">Destination</label>
<input asp-for="Trip.Destination" class="form-control">
<hr />
</div>
<div class="form-group">
<label asp-for="Trip.Accommodation">Accommodation</label>
<input asp-for="Trip.Accommodation" class="form-control">
<hr />
</div>
<div class="form-group">
<label asp-for="Trip.StartDate">Start Date</label>
<input asp-for="Trip.StartDate" class="form-control">
<hr />
</div>
<div class="form-group">
<label asp-for="Trip.EndDate">End Date</label>
<input asp-for="Trip.EndDate" class="form-control">
<hr />
</div>
<a class="btn btn-outline-dark" asp-controller="Trip" asp-action="Add">Next</a>
<a class="btn btn-outline-secondary " asp-controller="Trip" asp-action="Cancel">Cancel</a>
</form>
My model
namespace Trip_Log.Models
{
public class Trip
{
public int TripId { get; set; }
[Required(ErrorMessage = "Please enter a destination")]
public string Destination { get; set; }
[Required(ErrorMessage = "Please enter a start date")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "Please enter an end date")]
public DateTime EndDate { get; set; }
public string Accommodation { get; set; }
public string AccommodationPhone { get; set; }
public string AccommodationEmail { get; set; }
public string ThingToDo1 { get; set; }
public string ThingToDo2 { get; set; }
public string ThingToDo3 { get; set; }
public string ThingsToDo { get { return ThingToDo1 + "\n" + ThingToDo2 + "\n" + ThingToDo3; }
}
}
TripViewModel
public class TripViewModel
{
// Used to shape multiple entities from one or more models into a single object
//
public Trip Trip { get; set; }
public int PageNumber { get; set; }
}
First, seens like you posted the wrong model since in your controller you expected to receive TripViewModel and the model you showed is Trip.
Second, the validation goes to the top of the property, like this:
[Required(ErrorMessage = "Please enter an end date")]
public DateTime EndDate { get; set; }
You can try to replace anchor tag with button like this:
<input type="submit" value="submit" />
And then make sure you load jquery.validate.min.js and jquery.validate.unobtrusive.min.js,then when you click the button,form will be validated and go to action Add.
The reason it didn't work is because I was missing the hidden input field stating the page number.
<input type="hidden" asp-for="PageNumber" />
The next button is also needs to be like so, since as another user pointed out anchors use get.
<button class="btn btn-outline-dark" type="submit">Next</button>
Both the validation and redirects started working with these two changes applied to the View.
My code is similar to:
class StudentsViewModel:
public class StudentsViewModel
{
public List<Student> Students { get; set; }
public Student SelectedStudent { get; set; }
public string DisplayMode { get; set; }
}
StudentsController:
[HttpPost]
public ActionResult New(int? page, int? SelectedGroup)
{
// some code
StudentsViewModel model = new StudentsViewModel();
model.Students = db.Students.ToList().ToPagedList(pageNumber, pageSize);
model.SelectedStudent = null;
model.DisplayMode = "WriteOnly";
ViewBag.IDGroup = new SelectList(db.Groups, "IDGroup", "Name");
return View("Index", model);
}
View: Index
<form method="post">
<input type="submit" value="Add Student" formaction="/Students/new" class="btn btn-default" />
//some code
#{
if (Model.SelectedStudent != null)
{
if (Model.DisplayMode == "ReadWrite")
{
Html.RenderPartial("_EditStudent", Model.SelectedStudent);
}
}
if (Model.DisplayMode == "WriteOnly")
{
Html.RenderPartial("_InsertStudent", new StudentList.Models.Student());
}
}</form>
Partial View:
_InsertStudent.cshtml
<div class="form-group">
#Html.DropDownList("IDGroup", String.Empty)
#Html.ValidationMessageFor(model => model.IDGroup)
</div>
I have very big problem because my DropDownList doesn't work... Now I display _InsertStudent when I click on button but it doesn't work... If i have
Html.RenderPartial("_InsertStudent", new StudentList.Models.Student());
directly (without button) it works...
How is it possible that in a razor EditorTemplate the following commands generate a different value for the same ViewModel:
#Html.TextAreaFor(model => model.Value)
#Model.Value
And no, in the Value get property, the value is not changed
Update 1:
Sorry guys for the short message, you know, tired, frustrated...
Made a sample, got rid of all the partials and templates.
Give the textbox number 1, hit add, number 2, hit add, number 3, hit add.
The remove number 2.
The result is an out of sync between the textbox and the displayed value.
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
TestModel testModel = TestModel.Create();
Session["model"] = testModel;
return View("Index", testModel);
}
[HttpPost]
public ActionResult Submit(TestModel submitModel, string submit)
{
// merge values in current form
var testModel = Session["model"] as TestModel;
if (testModel == null) throw new Exception("No current model found.");
testModel.MergeFieldValues(submitModel);
if (submit.StartsWith("Add_"))
{
var rowGroupId = Guid.Parse(submit.Substring("Add_".Length));
TestRowGroup rowGroup = testModel.Groups.SelectMany(g => g.RowGroups).Single(rg => rg.RowGroupId == rowGroupId);
rowGroup.AddFieldRow();
}
if (submit.StartsWith("Del_"))
{
var fieldRowId = Guid.Parse(submit.Substring("Del_".Length));
testModel.RemoveFieldRow(fieldRowId);
}
return View("Index", testModel);
}
}
Model:
public class TestModel
{
public List<TestGroup> Groups { get; set; }
public static TestModel Create()
{
var testModel = new TestModel { Groups = new List<TestGroup>() };
var grp = new TestGroup { RowGroups = new List<TestRowGroup>() };
var rowGrp = new TestRowGroup { RowGroupId = Guid.NewGuid(), FieldRows = new List<TestFieldRow>() };
var fldRow = new TestFieldRow { FieldRowId = Guid.NewGuid(), Fields = new List<TestFormField>() };
var fld = new TestFormField { FieldId = Guid.NewGuid() };
fldRow.Fields.Add(fld);
rowGrp.FieldRows.Add(fldRow);
grp.RowGroups.Add(rowGrp);
testModel.Groups.Add(grp);
return testModel;
}
public void MergeFieldValues(TestModel src)
{
foreach (var srcField in src.Groups.SelectMany(g => g.RowGroups.SelectMany(rg => rg.FieldRows.SelectMany(fr => fr.Fields))))
{
var destField = Groups.SelectMany(g => g.RowGroups.SelectMany(rg => rg.FieldRows.SelectMany(fr => fr.Fields))).FirstOrDefault(f => f.FieldId == srcField.FieldId);
if (destField == null) throw new Exception("Field not found during merge");
destField.Value = srcField.Value;
}
}
public void RemoveFieldRow(Guid fieldRowId)
{
foreach (var group in Groups)
{
foreach (var rowGroup in group.RowGroups)
{
rowGroup.FieldRows.RemoveAll(fieldRow => fieldRow.FieldRowId == fieldRowId);
}
}
}
}
public class TestGroup
{
public List<TestRowGroup> RowGroups { get; set; }
}
public class TestRowGroup
{
public List<TestFieldRow> FieldRows { get; set; }
public Guid RowGroupId { get; set; }
public void AddFieldRow()
{
var newRow = new TestFieldRow
{
Fields = new List<TestFormField>()
};
newRow.FieldRowId = Guid.NewGuid();
var fld = new TestFormField { FieldId = Guid.NewGuid() };
newRow.Fields.Add(fld);
FieldRows.Add(newRow);
}
}
public class TestFieldRow
{
public Guid FieldRowId { get; set; }
public List<TestFormField> Fields { get; set; }
}
public class TestFormField
{
public Guid FieldId { get; set; }
public string Value { get; set; }
}
View:
#model FieldTest.Models.TestModel
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
#using (Html.BeginForm("Submit", "Home", FormMethod.Post))
{
for (int g = 0; g < Model.Groups.Count; g++)
{
for (int rg = 0; rg < Model.Groups[g].RowGroups.Count; rg++)
{
for (int fr = 0; fr < Model.Groups[g].RowGroups[rg].FieldRows.Count; fr++)
{
for (int f = 0; f < Model.Groups[g].RowGroups[rg].FieldRows[fr].Fields.Count; f++)
{
#Html.HiddenFor(model => model.Groups[g].RowGroups[rg].FieldRows[fr].Fields[f].FieldId)
#Model.Groups[g].RowGroups[rg].FieldRows[fr].Fields[f].Value
#Html.TextBoxFor(model => model.Groups[g].RowGroups[rg].FieldRows[fr].Fields[f].Value)
<button onclick="return confirm('Are you sure you would like to remove this row?');" type="submit" value="#string.Format("Del_{0}", Model.Groups[g].RowGroups[rg].FieldRows[fr].FieldRowId)" name="submit">Remove</button>
<hr />
}
}
<button type="submit" value="#string.Format("Add_{0}", Model.Groups[g].RowGroups[rg].RowGroupId)" name="submit">Add</button>
}
}
<input type="submit" value="Submit" name="submit" />
}
</body>
</html>
More importantly, are you sure this is an EditorTemplate problem? If you put the code in your main view, does it also happen? Did you try that? Or did you assume it was an EditorTemplate problem?
Since you neglected to provide any context for your question, all we can do is guess. More than likely, you have modified the contents of the view model in a post operation, and are now surprised that the Html helpers are using the old value rather than the value from the model.
If so, this is "by design", and a well documented (hundreds if not thousands of questions already here on SO about this issue). The MVC Helpers prefer the contents of the ModelState over the model itself in post operations. You have to clear the ModelState in order to work around it.
I'm rather new to the ASP.net MVC world and I'm trying to figure out how to render a group of checkboxes that are strongly typed to a view model. In webforms I would just use the checkboxlist control but im a bit lost with MVC.
I'm building a simple contact form for a wedding planning business and need to pass whatever checkbox values the user selects to my controller.
The form checkboxes need to look like this:
Your help would be greatly appreciated. Thanks!
Here's what I have so far.
CONTROLLER
[HttpPost]
public ActionResult Contact(ContactViewModel ContactVM)
{
if (!ModelState.IsValid)
{
return View(ContactVM);
}
else
{
//Send email logic
return RedirectToAction("ContactConfirm");
}
}
VIEW MODEL
public class ContactViewModel
{
[Required]
public string Name { get; set; }
[Required]
public string Phone { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
public string Subject { get; set; }
public IEnumerable<SelectListItem> SubjectValues
{
get
{
return new[]
{
new SelectListItem { Value = "General Inquiry", Text = "General Inquiry" },
new SelectListItem { Value = "Full Wedding Package", Text = "Full Wedding Package" },
new SelectListItem { Value = "Day of Wedding", Text = "Day of Wedding" },
new SelectListItem { Value = "Hourly Consultation", Text = "Hourly Consultation" }
};
}
}
//Not sure what I should do for checkboxes...
}
VIEW
#model NBP.ViewModels.ContactViewModel
#{
ViewBag.Title = "Contact";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
<div id="ContactContainer">
<div><span class="RequiredField">* </span>Your Name:</div>
<div>
#Html.TextBoxFor(model => model.Name)
</div>
<div><span class="RequiredField">* </span>Your Phone:</div>
<div>
#Html.TextBoxFor(model => model.Phone)
</div>
<div><span class="RequiredField">* </span>Your Email:</div>
<div>
#Html.TextBoxFor(model => model.Email)
</div>
<div>Subject:</div>
<div>
#Html.DropDownListFor(model => model.Subject, Model.SubjectValues)
</div>
<div>Vendor Assistance:</div>
<div>
<!-- CHECKBOXES HERE -->
</div>
<div>
<input id="btnSubmit" type="submit" value="Submit" />
</div>
</div>
}
You could enrich your view model:
public class VendorAssistanceViewModel
{
public string Name { get; set; }
public bool Checked { get; set; }
}
public class ContactViewModel
{
public ContactViewModel()
{
VendorAssistances = new[]
{
new VendorAssistanceViewModel { Name = "DJ/BAND" },
new VendorAssistanceViewModel { Name = "Officiant" },
new VendorAssistanceViewModel { Name = "Florist" },
new VendorAssistanceViewModel { Name = "Photographer" },
new VendorAssistanceViewModel { Name = "Videographer" },
new VendorAssistanceViewModel { Name = "Transportation" },
}.ToList();
}
[Required]
public string Name { get; set; }
[Required]
public string Phone { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
public string Subject { get; set; }
public IEnumerable<SelectListItem> SubjectValues
{
get
{
return new[]
{
new SelectListItem { Value = "General Inquiry", Text = "General Inquiry" },
new SelectListItem { Value = "Full Wedding Package", Text = "Full Wedding Package" },
new SelectListItem { Value = "Day of Wedding", Text = "Day of Wedding" },
new SelectListItem { Value = "Hourly Consultation", Text = "Hourly Consultation" }
};
}
}
public IList<VendorAssistanceViewModel> VendorAssistances { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new ContactViewModel());
}
[HttpPost]
public ActionResult Index(ContactViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
//Send email logic
return RedirectToAction("ContactConfirm");
}
}
View:
#using (Html.BeginForm())
{
<div id="ContactContainer">
<div><span class="RequiredField">* </span>Your Name:</div>
<div>
#Html.TextBoxFor(model => model.Name)
</div>
<div><span class="RequiredField">* </span>Your Phone:</div>
<div>
#Html.TextBoxFor(model => model.Phone)
</div>
<div><span class="RequiredField">* </span>Your Email:</div>
<div>
#Html.TextBoxFor(model => model.Email)
</div>
<div>Subject:</div>
<div>
#Html.DropDownListFor(model => model.Subject, Model.SubjectValues)
</div>
<div>Vendor Assistance:</div>
<div>
#for (int i = 0; i < Model.VendorAssistances.Count; i++)
{
<div>
#Html.HiddenFor(x => x.VendorAssistances[i].Name)
#Html.CheckBoxFor(x => x.VendorAssistances[i].Checked)
#Html.LabelFor(x => x.VendorAssistances[i].Checked, Model.VendorAssistances[i].Name)
</div>
}
</div>
<div>
<input id="btnSubmit" type="submit" value="Submit" />
</div>
</div>
}
Use a string array in your view model. You can then use the helper I hacked together. if you don't want to use the helper and the enum then see the actual Html at the bottom. The binder will return a string array with only the selected string values in it. if none are selected it returns a null value for your array. You must account for that, you have been warned :)
View Model:
[Display(Name = "Which Credit Cards are Accepted:")]
public string[] CreditCards { get; set; }
Helper:
public static HtmlString CheckboxGroup<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> propertySelector, Type EnumType)
{
var groupName = GetPropertyName(propertySelector);
var modelValues = ModelMetadata.FromLambdaExpression(propertySelector, htmlHelper.ViewData).Model;//propertySelector.Compile().Invoke(htmlHelper.ViewData.Model);
StringBuilder literal = new StringBuilder();
foreach (var value in Enum.GetValues(EnumType))
{
var svalue = value.ToString();
var builder = new TagBuilder("input");
builder.GenerateId(groupName);
builder.Attributes.Add("type", "checkbox");
builder.Attributes.Add("name", groupName);
builder.Attributes.Add("value", svalue);
var contextValues = HttpContext.Current.Request.Form.GetValues(groupName);
if ((contextValues != null && contextValues.Contains(svalue)) || (modelValues != null && modelValues.ToString().Contains(svalue)))
{
builder.Attributes.Add("checked", null);
}
literal.Append(String.Format("</br>{1} <span>{0}</span>", svalue.Replace('_', ' '),builder.ToString(TagRenderMode.Normal)));
}
return (HtmlString)htmlHelper.Raw(literal.ToString());
}
private static string GetPropertyName<T, TProperty>(Expression<Func<T, TProperty>> propertySelector)
{
var body = propertySelector.Body.ToString();
var firstIndex = body.IndexOf('.') + 1;
return body.Substring(firstIndex);
}
HTML:
#Html.CheckboxGroup(m => m.CreditCards, typeof(VendorCertification.Enums.CreditCardTypes))
Use this if helper extensions scare you:
<input id="CreditCards" name="CreditCards" type="checkbox" value="Visa"
#(Model.CreditCards != null && Model.CreditCards.Contains("Visa") ? "checked=true" : string.Empty)/>
<span>Visa</span><br />
<input id="CreditCards" name="CreditCards" type="checkbox" value="MasterCard"
#(Model.CreditCards != null && Model.CreditCards.Contains("MasterCard") ? "checked=true" : string.Empty)/>
<span>MasterCard</span><br />
For me this works too, and I think this is the simplest (reading the previous answers).
The viewmodel has a string[] for the check boxes.
public string[] Set { get; set; }
The view has this code, and you can repeat the input as many times you need. name, id of the input control has to match the name of the property of the viewmodel.
<div class="col-md-3">
<div class="panel panel-default panel-srcbox">
<div class="panel-heading">
<h3 class="panel-title">Set</h3>
</div>
<div class="panel-body">
<div class="form-group-sm">
<label class="control-label col-xs-3">1</label>
<div class="col-sm-8">
<input type="checkbox" id="Set" name="Set" value="1" />
</div>
<label class="control-label col-xs-3">2</label>
<div class="col-sm-8">
<input type="checkbox" id="Set" name="Set" value="2" />
</div>
</div>
</div>
</div>
</div>
On the post method the Set variable is an array, having the checked value(s).