How to capture multiple checkboxes and radio buttons posted data by viewmodel ASP.Net MVC - asp.net-mvc-4

i am new in MVC. so this is my html looks like
<form id='your-form' action='#Url.Action("Action","Controller")' method='post'>
<b>Gender</b><br />
<input type='radio' name='gender' value='Male' /> Male <br />
<input type='radio' name='gender' value='Female' /> Female <br />
<hr />
<b>Hobbies</b><br />
<input type='checkbox' name='hobbies' value='Reading' /> Reading <br />
<input type='checkbox' name='hobbies' value='Sports' /> Sports <br />
<input type='checkbox' name='hobbies' value='Movies' /> Movies <br />
<input type='submit' value='Update Profile' />
</form>
this way i am capturing data
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string gender, string[] hobbies)
{
// Example output
var output = String.Format("The user's gender is <b>{0}</b> and they enjoy <b>{1}</b>", gender, String.Join(",", hobbies));
return Content(output);
}
}
but i like to know how could i capture it by viewmodel concept. anyone can help me with sample code. thanks

View models
public class HobbyVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class PersonVM
{
....
public string Gender { get; set; } // would be better to use an enum
public List<HobbyVM> Hobbies { get; set; }
}
In the GET method, initialize an instance of the view model and pass it to the view
public ActionResult Create()
{
PersonVM model = new PersonVM()
{
Hobbies = new List<HobbyVM>()
{
new HobbyVM(){ ID = 1, Name = "Reading" },
new HobbyVM(){ ID = 2, Name = "Sports" },
....// etc these would actually be loaded from a repository
}
};
return View(model);
}
[HttpPost]
public ActionResult Create(PersonVM model)
{
// map you view model to a instance of your data model
// save and redirect
}
View
#model PersonVM
#Html.BeginForm())
{
....
<label>
#Html.RadioButtonFor(m => m.Gender, "Male", new { id = "" })
<span>Male</span>
</label>
<label>
#Html.RadioButtonFor(m => m.Gender, "Female", new { id = "" })
<span>Female</span>
</label>
for(int i = 0; i < Model.Hobbies.Count; i++)
{
#Html.HidenFor(m => m.Hobbies[i].ID)
#Html.CheckBoxFor(m => m.Hobbies[i].IsSelected)
#Html.LabelFor(m => m.Hobbies[i].IsSelected, Model.Hobbies[i].Name)
}
<input type="submit" />
}

Related

Why this Model Binding not working in Razor Page

I am using ASP.NET Core 3.1 with a simple example to test model binding to post a form. The property to be bound is an object named "Student". Bud the model binding is not working with post method. I will appreciate any help to point out what's wrong here.
Here are the code of my test programs:
'Student Class':
namespace ModelBindPost.Models
{
public class Student
{
public int Id;
public string FirstName;
public string LastName;
}
}
'Edit.cshtml.cs'
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using ModelBindPost.Models;
namespace ModelBindPost.Pages
{
public class EditModel : PageModel
{
[BindProperty(SupportsGet = true)]
public Student Student { get; set; }
public EditModel()
{
Student = new Student();
}
public IActionResult OnGet()
{
Student.Id = 1;
Student.FirstName = "Jean";
Student.LastName = "Smith";
return Page();
}
public IActionResult OnPost()
{
string name = this.Student.FirstName;
return Page();
}
}
}
' Edit.cshtml':
#page
#model ModelBindPost.Pages.EditModel
#{
}
<h2>Model Binding Test</h2>
<form method="post">
<div class="form-group">
<lable asp-for="Student.Id"></lable>
<input asp-for="Student.Id" class="form-control" />
</div>
<div class="form-group">
<lable asp-for="Student.FirstName"></lable>
<input asp-for="Student.FirstName" class="form-control" />
</div>
<div class="form-group">
<lable asp-for="Student.LastName"></lable>
<input asp-for="Student.LastName" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
A simple public field cannot work for model binding. You need add getter and setter to create property like below:
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

Cannot update user Identity Role from list in razor page

I have a razor page which shows checkbox of Roles. The Roles owned by the selected user will be checked on page load. What I'm trying to do is, I want to be able to edit the roles for the selected user. But when I click update, it doesn't update.
Here is the razor page:
<EditForm Model="#RoleDto" OnValidSubmit="#EditRole">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="card">
<div class="card-header">
<h2>Manage User Roles</h2>
Add/Remove Roles for User / #UserFullname
</div>
<div class="card-body">
#for (int i = 0; i < numOfRoles; i++)
{
<div class="form-check m-1">
<input type="hidden" value="#RoleListModel[i].Id" />
<input type="hidden" value="#RoleListModel[i].Name" />
<input type="checkbox" checked="#RoleListModel[i].Selected" /> #RoleListModel[i].Name
</div>
}
</div>
</div>
<button type="submit" class="btn btn-success btn-block">
Confirm
</button>
#code {
ApplicationRoleDto RoleDto = new ApplicationRoleDto();
private List<ApplicationRoleDto> RoleListModel;
[Parameter] public string Id { get; set; }
[Parameter] public ApplicationUserDto UserDto { get; set; }
[Parameter] public string UserFullname { get; set; }
[Parameter] public int numOfRoles { get; set; }
protected async override Task OnParametersSetAsync()
{
UserDto = await _client.GetFromJsonAsync<ApplicationUserDto>($"api/userroles/{Id}");
UserFullname = UserDto.FullName;
RoleListModel = await _client.GetFromJsonAsync<List<ApplicationRoleDto>>($"api/rolemanager/{Id}");
numOfRoles = RoleListModel.Count();
}
async Task EditRole()
{
await _client.PostAsJsonAsync($"api/rolemanager/{Id}", RoleListModel);
_navManager.NavigateTo($"/userroles/");
}
}
and here is the controller:
[HttpPost]
public async Task<IActionResult> Manage(List<ApplicationRoleDto> model, string Id)
{
var user = await _userManager.FindByIdAsync(Id);
if (user == null)
{
NotFound();
}
var roles = await _userManager.GetRolesAsync(user);
var result = await _userManager.RemoveFromRolesAsync(user, roles);
if (!result.Succeeded)
{
Console.WriteLine("Cannot remove user existing roles");
return NotFound();
}
result = await _userManager.AddToRolesAsync(user, model.Where(x => x.Selected).Select(y => y.Name));
if (!result.Succeeded)
{
Console.WriteLine("Cannot add selected roles to user");
return NotFound();
}
return NoContent();
}
Did I miss anything here?

MVC checkbox list bounding to model

I am trying to collect all the options that the user have selected for a checkbox list. The checkbox list is built using a foreach loop and I have a int[] that I am trying to put the id into. Any help would be great.
View
#{
int idxFormats = 0;
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
#Html.HiddenFor(m => Model.selectedFormats[idxFormats]);
</div>
idxFormats++;
}
#Html.ValidationMessageFor(model => model.selectedFormats[idxFormats])
}
Model
public List<GenericValues> ListOfFormats { get; set; }
[Display(Name = "At least one 'Format' must be selected")]
public int[] selectedFormats { get; set; }
Change the Checkbox name to selectedFormats
<input type="checkbox" value=#item.Value name="selectedFormats" />
Test example:
Model:
public class Test
{
public List<GenericValues> ListOfFormats { get; set; }
public int[] selectedFormats { get; set; }
}
public class GenericValues
{
public int Value { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
}
View:
#model Test
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Index</h1>
<form method="post">
#{
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="selectedFormats" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
</div>
}
}
<input type="submit" value="submit" />
</form>
Controller:
public IActionResult Index()
{
Test test = new Test
{
ListOfFormats = new List<GenericValues>
{
new GenericValues
{
Name = "A",
Value = 1,
},
new GenericValues
{
Name = "B",
Value = 2,
},
new GenericValues
{
Name = "C",
Value = 3,
}
}
};
return View(test);
}
[HttpPost]
public IActionResult Index(Test test)
{
return Ok();
}
Result:
if you are looking to put id as value of your idxFormats then use this code in your checkbox:
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats" />
Edit:
I am not so familiar with c#, I tested with minimum code :
// Replace the model correct path by yours
#model IEnumerable<WebApplication1.Models.MyModels.ListOfFormats>
#{
int idxFormats = 0;
foreach (var item in Model)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats"/>
<label>#Html.Raw(#item.Name)</label>
</div>
idxFormats++;
}
}

Saving multiple records on submit click into differnt entities in MVC4. Not getting values from view in Controller

I am trying to save the class attendance for multiple students on click of submit button. I am able to create the blank records in the concern tables and then populate the data in view.
I have the following view model:
public class TeacherAttendanceModel
{
#region Required Properties
public long ScholarAttendanceId { get; set; }
public string Student { get; set; }
public bool Absent { get; set; }
public string AbsentComment { get; set; }
public bool Uniform { get; set; }
public bool Homework { get; set; }
public string HomeworkComment { get; set; }
public String UniformCommentSelected { get; set; }
public IEnumerable<String> UniformComment { get; set; }
#endregion
}
My Controller is as below.
public class TeacherAttendanceController : Controller
{
//
// GET: /TeacherAttendance/
public ActionResult Index()
{
long classId = Success.Business.Roles.Teacher.GetHomeRoomClassID(Convert.ToInt64(Session[GlobalVar.LOGGED_IN_ID]));
var classAttendanceStatus = Success.Business.Entities.ClassAttendance.GetClassAttendanceStatus(classId);
ViewBag.status = classAttendanceStatus;
var attendanceData = TeacherAttendance.CreateClassAttendance(classId);
return View(attendanceData);
}
[HttpPost]
public ActionResult Index(IEnumerable<TeacherAttendanceModel> teacherAttendanceModel)
{
try
{
if (ModelState.IsValid)
{
TeacherAttendance.SaveAttendance(teacherAttendanceModel);
}
}
catch (Exception e)
{
}
return View(teacherAttendanceModel);
}
}
Get Index is working fine. But I am not getting the TeacheAttendanceModel object in Post index. I get null object. I would be thank full to get any help in this regards. How to update the multiple records of attendance on submit click?
I am using the following View:
#foreach (var item in Model) {
<tr >
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.DisplayFor(modelItem => item.Student)
</td>
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.CheckBoxFor(modelItem => item.Absent, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
#Html.TextBoxFor(modelItem => item.AbsentComment, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
</td>
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.CheckBoxFor(modelItem => item.Uniform, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
#Html.DropDownListFor(modelItem => item.UniformCommentSelected, new SelectList(item.UniformComment),item.UniformCommentSelected ?? "---Select---", ViewBag.status == 2? new {disabled = "disabled"} : null)
</td>
<td style="border-style:solid; border-color:darkslategray; border-width:thin;">
#Html.CheckBoxFor(modelItem => item.Homework, ViewBag.status == 2 ? new {disabled = "disabled"} : null)
#Html.TextBoxFor(modelItem => item.HomeworkComment, ViewBag.status == 2? new {disabled = "disabled"} : null)
</td>
</tr>
}
Model:
public class Test
{
public List<string> UniformComment { get; set; }
}
Controller:
public ActionResult Index()
{
var model = new Test
{
UniformComment = new List<string>{ "one", "two", "three" }
};
return View(model);
}
[HttpPost]
public ActionResult Index(Test model)
{
return View(model);
}
View:
#using (Html.BeginForm())
{
for (var i = 0; i < Model.UniformComment.Count; i++)
{
#Html.TextBoxFor(x => Model.UniformComment[i])
}
<input type="submit" value="Save" />
}
Rendered html example:
<input id="UniformComment_0_" name="UniformComment[0]" type="text" value="one" />
<input id="UniformComment_1_" name="UniformComment[1]" type="text" value="two" />
<input id="UniformComment_2_" name="UniformComment[2]" type="text" value="three" />
The idea is iterate with for loop or create EditorTemplate and then you receive indexed items.
Added (Feel the difference):
View:
#using (Html.BeginForm())
{
foreach (var comment in Model.UniformComment)
{
#Html.TextBoxFor(x => comment)
}
<input type="submit" value="Save" />
}
Rendered html:
<input id="comment" name="comment" type="text" value="one" />
<input id="comment" name="comment" type="text" value="two" />
<input id="comment" name="comment" type="text" value="three" />
Use a IList instead of IEnumerable in the view and replace the foreach loop with a for loop.
Step 1:
Use
#model IList<TeacherAttendanceModel>
instead of
#model IEnumerable<TeacherAttendanceModel>
Step 2:
Use
#for (var i = 0; i < Model.Count; i++)
instead of
#foreach (var item in Model)
Refer How to pass IEnumerable list to controller in MVC including checkbox state? for more details.

MVC4 sending model propert id to controller class

How to send id of a model property Name to Controller class in an MVC4 application
public class{
public Name{get;set;}
}
For Accesing name using id of that property
Update:
Here if change Name using jquery at runtime i want to send the changed name id to the controller class
UPDate:
This is my VIew
<script type="text/javascript">
$(function () {
$('.editor input').blur(function () {
$(this).hide();
$(this).closest('p').find('label').html($(this).val()).show();
});
$('.editor label').click(function () {
$(this).hide();
$(this).closest('p').find('input').show();
});
});
#using (Html.BeginForm("Homepage", "Home", FormMethod.Post))
{
<div class="editor">
<p>
#Html.LabelFor(x => x.Name, Model.Name)
#Html.EditorFor(x => x.Name)
<input type="submit" value="OK" />
</p>
<p>
#Html.LabelFor(x => x.Company, Model.Company)
#Html.EditorFor(x => x.Company)
<input type="submit" value="OK" />
</p>
<p>
#Html.LabelFor(x => x.City, Model.City)
#Html.EditorFor(x => x.City)
<input type="submit" value="OK" />
</p>
</div>
<input type="submit" value="OK" />
}
This is my model
public class Details
{
public string Name
{ get; set; }
public string Company
{ get; set; }
public string City
{ get; set; }
}
This is my COntroller methods
public ActionResult Homepage(Details d)
{
d.Name = "Rakesh";
d.Company = "TCS";
d.City = "DElhi";
return View(d);
}
[HttpPost, ActionName("Homepage")]
public ActionResult Indexof(Details d)
{
return View(d);
}
Here i am editing and sending data to the controller but my problem is when i click on Rakesh for example and change the name then i need to click button twice then only the changed data is sent to the controller class
Model:
public class SomeModel {
public string Name { get; set; }
}
Controller:
[HttpPost]
public ActionResult YourAction( SomeModel m )
{
if( ModelState.IsValid )
{
// use model
var name = m.Name;
return RedirectToAction( "Index", "Home" );
}
return View( m );
}
If this isn't what you need, please clarify what's this "id" you're talking about.