I have some problem with the MVC, I'll try to describe. I have 2 class in my model.
public class ApplicationPermissionVM
{
public ApplicationPermission Permission { get; set; }
public bool IsSelected { get; set; }
}
public class RoleAndPermissonsModel
{
//Constructor skipped
public ApplicationRole ApplicationRole { get; set; }
public IEnumerable<ApplicationPermissionVM> Permissions { get; set; }
}
The second model is the main model, and I initialize the model in controller. The ApplicationRole is null and I have got 19 element in the list. When I POST the form the ApplicationRole member will be created, but the Permissions list will be empty so will lost all selection. If anyone knows what is the problem please write to me.
Controller:
[HttpGet]
public ActionResult NewRole()
{
_model = new RoleAndPermissonsModel();
return View(_model);
}
[HttpPost]
public ActionResult NewRole(RoleAndPermissonsModel newRole)
{
if (ModelState.IsValid)
{
var id = _applicationRoleService.AddNewRole(newRole.ApplicationRole);
_applicationRoleService.AssignPermissionsToRole(newRole.SelectedItems, id);
}
return RedirectToAction("Index");
}
View:
#model EO.Core.WebUI.Models.RoleAndPermissonsModel
#using (Html.BeginForm("NewRole", "PermissionRole", FormMethod.Post, new { id = "frmNewRole" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>ApplicationRole</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ApplicationRole.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ApplicationRole.Name)
#Html.ValidationMessageFor(model => model.ApplicationRole.Name)
</div>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.IsSelected)
</th>
<th></th>
</tr>
#foreach (var item in Model.Permissions)
{
<tr>
<td>
#Html.EditorFor(modelItem => item.IsSelected)
</td>
<td>
#Html.DisplayFor(modelItem => item.Permission.Name);
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
you need manually to loop through the list and output it like
<input type="text"
id="Permissions[0].IsSelected"
name="Permissions[0].IsSelected" value="" />
so, change your code to:
#for(int i = 0; i < Model.Permissions.Count; i++)
{
<tr>
<td><input type="checkbox"
id="Permissions[#(i)].IsSelected"
name="Permissions[#(i)].IsSelected" /></td>
<td><input type="text"
id="Permissions[#(i)].Permission.Name"
name="Permissions[#(i)].Permission.Name" /></td>
</tr>
}
because you have an object inside your type Permissions remember to initialiate it or you will get a null reference.
public class RoleAndPermissonsModel
{
public RoleAndPermissonsModel() {
this.Permissions = new List<ApplicationPermissionVM>();
}
public ApplicationRole ApplicationRole { get; set; }
public IEnumerable<ApplicationPermissionVM> Permissions { get; set; }
}
or you can easily create a ViewModel instead and use that to interlink your Model to your View.
Note: I do wonder, if your list is always null (as you are passing an empty/null list) why are you looping through Model.Permissions ?
In order to do the "EDIT" view, the loop code should be:
#for(int i = 0; i < Model.Permissions.Count; i++)
{
<tr>
<td><input type="checkbox"
#(Permissions[i].IsSelected ? "checked='checked'" : "")
id="Permissions[#(i)].IsSelected"
name="Permissions[#(i)].IsSelected" /></td>
<td><input type="text"
id="Permissions[#(i)].Permission.Name"
name="Permissions[#(i)].Permission.Name"
value="#(Permissions[i].Permission.Name)" /></td>
</tr>
}
all you need to add is checked to the checkbox if it's selected and fill the permission name to the other input.
Related
I have an asp.net core 3.1 mvc project where I have a search page (view). I am persisting search, filter and sort criteria values via Session data. This works fine, and persists data correctly, but the querystring does not contain all the information I need it to.
Values for the filters and search are selected via a form, and submit button, but sorting is selected by clicking the column headers in the search results. e.g.:
<form asp-controller="Companies" asp-action="Index" method="get">
<p>
<label>Company Name: </label>
<select asp-for="CompanyName" asp-items="Model.CompanyName">
<option value="">All</option>
</select>
<input type="submit" value="Find" />
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
<a asp-action="Index" asp-route-sortOrder="CompanyName">#Html.DisplayNameFor(model => model.CompaniesListViewModelList[0].CompanyName)</a>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.CompaniesListViewModelList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CompanyName)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
If the clicks in the header to change the sort order, none of the querystring values for the filters etc appear in the querystring.
The reason I need this is so that a link can be sent to someone else.
So the question is, how do I get all the used querystring values to appear in the querystring?
In the Index action method, you could use ViewBag or ViewData to store the current search value (the CompanyName), then transfer it to the view page:
Then, for the sort links, you could use asp-route-{value} to add the current search value as the route parameter, and bind values via the ViewData or ViewBag. Code like this:
<a asp-action="Index" asp-route-CompanyName="#ViewData["CurrentFilter"]" asp-route-sortOrder="#ViewData["CompanyNameSortParm"]">CompanyName</a>
The sample code as below:
Models:
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string CompanyName { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public List<Employee> Employees { get; set; }
}
public class EmployeeVM
{
public string CompanyName { get; set; }
public List<Company> AllCompanies { get; set; }
public List<Employee> Employees { get; set; }
}
Controller:
public class CompaniesController : Controller
{
public IActionResult Index(string sortOrder, string CompanyName)
{
ViewData["CompanyNameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "companyname_desc" : "";
ViewData["CurrentFilter"] = CompanyName;
var employees = from s in repo.GetEmployees()
select s;
if (!String.IsNullOrEmpty(CompanyName))
{
employees = employees.Where(s => s.CompanyName.Contains(CompanyName));
}
switch (sortOrder)
{
case "companyname_desc":
employees = employees.OrderByDescending(s => s.CompanyName);
break;
default:
employees = employees.OrderBy(s => s.EmployeeId);
break;
}
EmployeeVM vm = new EmployeeVM();
vm.Employees = employees.ToList();
vm.AllCompanies = repo.GetAllCompanies().ToList();
return View(vm);
}
}
Index Views:
#model netcore3.Data.EmployeeVM
<form asp-controller="Companies" asp-action="Index" method="get">
<p>
<label>Company Name: </label>
<select asp-for="CompanyName" asp-items="#(new SelectList(Model.AllCompanies, "CompanyName","CompanyName"))">
<option value="">All</option>
</select>
<input type="submit" value="Find" />
</p>
</form>
<table class="table">
<thead>
<tr>
<th>
EmployeeName
</th>
<th>
<a asp-action="Index" asp-route-CompanyName="#ViewData["CurrentFilter"]" asp-route-sortOrder="#ViewData["CompanyNameSortParm"]">CompanyName</a>
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Employees)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.EmployeeName)
</td>
<td>
#Html.DisplayFor(modelItem => item.CompanyName)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.EmployeeId">Edit</a> |
<a asp-action="Details" asp-route-id="#item.EmployeeId">Details</a> |
<a asp-action="Delete" asp-route-id="#item.EmployeeId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
The result like this:
Reference:
Tutorial: Add sorting, filtering, and paging - ASP.NET MVC with EF Core
Anchor Tag Helper in ASP.NET Core
I'm using asp.net-core with razor pages. I'm trying to update the checkboxes in the table.
When clicking on button save I pass with asp-route-for because I want to know how many items are in the list But my IList usersAccessRights is returning count = 0 and skips my foreach in update function. Is there other way to receive how many items and update the table checkboxes?
cshtml.cs:
public IActionResult OnPost(int id, string groupAccessName, bool chkDefaultGroup, IList<OutputAccessRights> usersAccessRights, string returnUrl = null){
Update(Convert.ToInt16(groupAccessID),usersAccessRights);
return RedirectToAction("Group AccessDetails", "Form", new { id = GroupAccessID, searchString = SearchString, searchInt = SearchInt }).WithSuccess("Success!", "Updated item!");
}
private void Update(short GroupAccessID, IList<OutputAccessRights> usersAccessRights)
{ Security Security = new Security();
IDataReader dr;
byte MainMenuId = 0;
byte SubMenuId = 0;
string Operation = "";
string OperationId = "";
foreach (var item in usersAccessRights)
{
MainMenuId = Convert.ToByte(item.MainMenuID);
SubMenuId = Convert.ToByte(item.SubMenuID);
//*** Add
OperationId = "A";
if (item.ChkAddRight == true)
Operation = "ADD";
else
Operation = "REMOVE";
Security.GroupAccessRightsMaintain(BellaMain.GlobalVariable.SystemID, Convert.ToInt16(GroupAccessID), MainMenuId, SubMenuId, OperationId, Operation);
//*** Delete
cshtml - button save:
<div class="col-sm-4">
#if (Model.Details != true)
{
<button type="submit" class="btn btn-primary" asp-page="Group AccessDetails" asp-route-usersAccessRights="#Model.UsersAccessRights">#Localizer["Save"]</button>
}
<a asp-page="Group Access" asp-route-searchString="#Model.SearchString" asp-route-searchInt="#Model.SearchInt">#Localizer["Back to Group"]</a>
</div>
cshtml-table UsersAccessRights:
#if (Model.UsersAccessRights != null)
{<table class="table table-striped table-bordered dataTable tableAccessRights" id="tableAccessRights" style="width:100%">
<thead>
<tr>
<th>
MainMenu
</th>
<th>
SubMenu
</th>
<th>
Operation
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.UsersAccessRights){ <tr>
<td>
#if (Model.GroupAccessID == 0)
{
<input type="checkbox" class="form-check-inline" name="#item.ChkUserAccessRights" id="chkUserAccessRights" asp-for="#item.ChkUserAccessRights"/>
#Html.DisplayFor(modelItem => item.MainMenuDescription)
}
else
{
#if (Model.Details != true)
{
<input type="checkbox" class="form-check-inline" name="#item.ChkUserAccessRights" id="chkUserAccessRights" asp-for="#item.ChkUserAccessRights"/>
#Html.DisplayFor(modelItem => item.MainMenuDescription)
<span class="text-danger"></span>
}
else
{
<input type="checkbox" class="form-check-inline" name="#item.ChkUserAccessRights" id="chkUserAccessRights" disabled readonly="readonly" />
#Html.DisplayFor(modelItem => item.MainMenuDescription)
}
}
</td>
<td>
#Html.DisplayFor(modelItem => item.SubMenuDescription)
</td>
<td>
#if (Model.GroupAccessID == 0)
{
<input type="checkbox" class="form-check-inline" name="#item.ChkAddRight" id="chkAddRight" asp-for="#item.ChkAddRight"/>
<label for="chkAddRight">Insert</label>
}
else
{
#if (Model.Details != true)
{
<input type="checkbox" class="form-check-inline" name="#item.ChkAddRight" id="chkAddRight" asp-for="#item.ChkAddRight"/>
<label for="chkAddRight">Insert</label>
<span class="text-danger"></span>
}
else
{
<input type="checkbox" class="form-check-inline" name="#item.ChkAddRight" id="chkAddRight" disabled readonly="readonly" asp-for="#item.ChkAddRight"/>
<label for="chkAddRight">Insert</label>
}
}
}
Here is a simple demo like below:
1.Model:
public class OutputAccessRights
{
public int Id { get; set; }
public bool ChkUserAccessRights { get; set; }
public string SubMenuDescription { get; set; }
public string MainMenuDescription { get; set; }
public bool ChkAddRight { get; set; }
}
2.Edit.cshtml:
<form method="post">
<table class="table table-striped table-bordered dataTable tableAccessRights" id="tableAccessRights" style="width:100%">
<thead>
<tr>
<th>
MainMenu
</th>
<th>
SubMenu
</th>
<th>
Operation
</th>
</tr>
</thead>
<tbody>
#for (var i = 0; i < Model.UsersAccessRights.Count(); i++)
{
<tr>
<td>
<input class="form-check-inline"asp-for="UsersAccessRights[i].ChkUserAccessRights" />
#Model.UsersAccessRights[i].MainMenuDescription
</td>
<td>
#Model.UsersAccessRights[i].SubMenuDescription
</td>
<td>
<input class="form-check-inline" asp-for="UsersAccessRights[i].ChkAddRight" />
<label for="chkAddRight">Insert</label>
</td>
</tr>
}
</tbody>
</table>
<button type="submit" class="btn btn-primary" >Save</button>
</form>
3.Edit.cshtml.cs:
public class EditModel : PageModel
{
private readonly RazorContext _context;
public EditModel(RazorContext context)
{
_context = context;
}
[BindProperty]
public IList<OutputAccessRights> UsersAccessRights { get; set; }
public async Task<IActionResult> OnGetAsync()
{
UsersAccessRights = await _context.OutputAccessRights.ToListAsync();
if (UsersAccessRights == null)
{
return NotFound();
}
return Page();
}
public async Task<IActionResult> OnPostAsync(IList<OutputAccessRights> usersAccessRights)
{
//do your stuff...
}
}
4.Result:
Is there any way I can have multiple drop-down menu displaying the data from the same database entity on the same razor page without creating several classes with new IDs (e.g. ResourceID; ResourceID1; ResourceID2)
I am able to display the drop down with the appropriate data from the MS SQL database in the 'Create.cshtml' and 'Edit.cshtml' razor pages, but the chosen data when saved displays the ID of the chosen resource instead of the name of the resource in the 'Index.cshtml', 'Detail.cshtml' and 'Delete.cshtml' views.
The Resource model:
namespace ProjectReporting.Models
{
public class Resource
{
public int ID { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Long Name")]
public string LongName { get; set; }
[DefaultValue(true)]
[Display(Name = "Active")]
public bool IsActive { get; set; } = true;
[Display(Name = "Is Manager")]
public bool IsManager { get; set; }
[Display(Name = "Is Forecast Owner")]
public bool IsForecastOwner { get; set; }
public ICollection<Project> Projects { get; set; }
}
}
The Project model:
namespace ProjectReporting.Models
{
public class Project
{
public int ID { get; set; }
[Display(Name = "ID")]
public int PID { get; set; }
[Display(Name = "Project Name")]
public string ProjectName { get; set; }
[Display(Name = "Forecast Owner")]
public int ResourceID { get; set; }
public Resource Resource { get; set; }
[Display(Name = "DSM")]
public int? ResourceID1 { get; set; }
public ICollection<ProjectComment> ProjectComments { get; set; }
}
}
The Create.cshtml page:
#page
#model ProjectReporting.Pages.Projects.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Project</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Project.PID" class="control-label"></label>
<input asp-for="Project.PID" class="form-control" />
<span asp-validation-for="Project.PID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Project.ProjectName" class="control-label"></label>
<input asp-for="Project.ProjectName" class="form-control" />
<span asp-validation-for="Project.ProjectName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Project.ResourceID" class="control-label"></label>
<select asp-for="Project.ResourceID" class="form-control" asp-items="ViewBag.ResourceID"><option value="" default="" selected="">-- Select --</option></select>
</div>
<div class="form-group">
<label asp-for="Project.ResourceID1" class="control-label"></label>
<select asp-for="Project.ResourceID1" class="form-control" asp-items="ViewBag.ResourceID1"><option value="" default="" selected="">-- Select --</option></select>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Project.IsArchived" /> #Html.DisplayNameFor(model => model.Project.IsArchived)
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
The Create.cshtml page:
namespace ProjectReporting.Pages.Projects
{
public class CreateModel : PageModel
{
private readonly ProjectReporting.Data.ApplicationDbContext _context;
public CreateModel(ProjectReporting.Data.ApplicationDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
ViewData["OrganisationID"] = new SelectList(_context.ProjectType.Where(a => a.IsActive == true), "ID", "TypeName");
ViewData["ResourceID"] = new SelectList(_context.Resource.Where(a => a.IsActive & a.IsForecastOwner == true), "ID", "LongName");
ViewData["ResourceID1"] = new SelectList(_context.Resource.Where(a => a.IsActive == true), "ID", "LongName");
return Page();
}
[BindProperty]
public Project Project { get; set; }
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Project.Add(Project);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
}
The Index.cshtml page:
#page
#model ProjectReporting.Pages.Projects.IndexModel
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-page="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Project[0].PID)
</th>
<th>
#Html.DisplayNameFor(model => model.Project[0].Organisation)
</th>
<th>
#Html.DisplayNameFor(model => model.Project[0].ProjectName)
</th>
<th>
#Html.DisplayNameFor(model => model.Project[0].Resource)
</th>
<th>
#Html.DisplayNameFor(model => model.Project[0].ResourceID1)
</th>
<th>
#Html.DisplayNameFor(model => model.Project[0].IsArchived)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Project) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.PID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Organisation.OrgName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ProjectName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Resource.LongName)
</td>
<td>
#Html.DisplayFor(modelItem => c)
</td>
<td>
#Html.DisplayFor(modelItem => item.IsArchived)
</td>
<td>
<a asp-page="./Edit" asp-route-id="#item.ID">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.ID">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
The item.Resource.LongName works fine for the first resource, but I would like the same to happen with the item.Resource.LongName.
The Index.cshtml.cs
namespace ProjectReporting.Pages.Projects
{
public class IndexModel : PageModel
{
private readonly ProjectReporting.Data.ApplicationDbContext _context;
public IndexModel(ProjectReporting.Data.ApplicationDbContext context)
{
_context = context;
}
public IList<Project> Project { get;set; }
public async Task OnGetAsync()
{
Project = await _context.Project
.Include(p => p.Resource).ToListAsync();
}
}
}
I have set the FK in the migration file to create the DB to be able to retrieve the data and would like to avoid having to create one class file by resource.
table.ForeignKey(
name: "FK_Project_Resource_ResourceID",
column: x => x.ResourceID,
principalTable: "Resource",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Project_Resource_ResourceID1",
column: x => x.ResourceID1,
principalTable: "Resource",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
The result shows the right data in the drop-down and the correct Resource ID selected when saved. However, the index, details and delete page only display the ResourceID instead of the LongName. If I use Resource.LongName for the second ResourceID1, it rightly displays the same LongName than for ResourceID.
How can I have multiple resource drop-down on the page that point to the same entity and display the LongName on the Index, Detail and Delete pages?
It is not clear about your relationships between Resource and Project, and you could not use both ResourceID and ResourceID1 for a Resource property for restoring different resources.
For many-to-many relationships, you could refer to
https://learn.microsoft.com/en-us/ef/core/modeling/relationships#many-to-many
A workaround is that you just get all resources in handler and retrieve it in view:
Index.cshtml.cs:
public class IndexModel : PageModel
{
private readonly ProjectReporting.Data.ApplicationDbContext _context;
public IndexModel(ProjectReporting.Data.ApplicationDbContext context)
{
_context = context;
}
public IList<Project> Project { get;set; }
public IList<Resource> Resources { get; set; }
public async Task OnGetAsync()
{
Resources = await _context.Resource.ToListAsync();
Project = await _context.Projects
.Include(p => p.Resource).ToListAsync();
}
}
Index.cshtml:
<td>
#Html.DisplayFor(modelItem => item.Resource.LongName)
</td>
<td>
#{
var resource = Model.Resources.FirstOrDefault(r => r.ID == item.ResourceID1);
}
#resource.LongName
</td>
I am trying to create a form where in user can add controls. I have main view
#model MVCDynamicFormGenerator.Models.FormViewModel
#{
ViewBag.Title = "Create";
}
#using (#Html.BeginForm())
{
<fieldset>
#Html.HiddenFor(form => form.Form.Uid)
#Html.Hidden("ListFields", ViewData["ListFields"])
<p>
#Html.LabelFor(form => form.Form.FormName)
#Html.TextBoxFor(form => form.Form.FormName)
</p>
<div id="FormFieldList">
#foreach (var formfield in Model.FormFields)
{
switch (formfield.ControlType)
{
case ("Textbox"):
Html.RenderPartial("Textbox", formfield);
break;
}
}
</div>
<h4>
[+] Add a Field
</h4>
<div id="FieldType">
<table>
<tr>
<th>
Select a Field Type
</th>
</tr>
<tr>
<td>
#Html.DropDownList("FieldTypes", new SelectList(Model.FormFields[0].FormFieldTypes, "Value", "Text"), new { id = "SelectedFieldUid" })
#Html.ActionLink("Add Field", "NewFormField", new { formId = ViewContext.FormContext.FormId, selectedFieldType = "SelectedFieldUid" }, new { id = "newFormField" })
#Html.ValidationMessageFor(model => model.FormFields)
</td>
</tr>
</table>
</div>
<p>
<input type="submit" value="Create" />
<input type="button" value="Cancel" '#Url.Action("List")');" />
</p>
</fieldset>
}
On dropdown change I am loading a partial view which is working(User can add n number of times)
#model MVCDynamicFormGenerator.Models.FormFieldViewModel
<div class="FormField">
#using (#Html.BeginForm())
{
<table>
<tr>
<th>
Form Field
</th>
<th>
Field Type
</th>
</tr>
<tr>
<td style="width: 45%;">
#Html.TextBoxFor(formfield => formfield.FormFieldName)
#Html.ValidationMessageFor(formfield => formfield.FormFieldName)
</td>
<td style="width: 25%;">
#Html.DropDownListFor(formfield => formfield.SelectedFormFieldType,
new SelectList(Model.FormFieldTypes, "Value", "Text",
Model.SelectedFormFieldType),
new { disabled = "disabled" })
#Html.HiddenFor(formfield => formfield.SelectedFormFieldType)
#Html.ValidationMessageFor(formfield => formfield.SelectedFormFieldType)
</td>
</tr>
</table>
}
</div>
/// form models
public class FormViewModel
{
//Properties
public Form Form { get; set; }
public List<FormFieldViewModel> FormFields { get; set; }
//Constructor
public FormViewModel()
{
Form = new Form();
FormFields = new List<FormFieldViewModel>();
}
}
public class FormFieldViewModel
{
public string FormFieldName { get; set; }
public string SelectedFormFieldType { get; set; }
}
controller methods
[HttpPost]
public ActionResult Create(FormViewModel viewModel)
{
return View();
}
All the field information related to main view gets available but FormFieldViewModel list gives zero count
Any help or suggestion to fix this
I have strongly typed view showing data from
ViewModel
public class GoldSetnUsers
{
bool Public { get; set; }
public List<GSUsers> gsUsers { get; set; }
public GoldSetnUsers()
{
UsersContext _dbm = new UsersContext();
this.gsUsers = _dbm.UserProfiles.Select(n => new GSUsers { UserName = n.UserName, isEditor = false, isReviewer = false }).ToList();
}
public class GSUsers
{
public string UserName { get; set; }
public bool isEditor { get; set; }
public bool isReviewer { get; set; }
}
}
Controller Httpget method display this view
Problem is, post-back model returns all rows check boxes as false. The check-box outside table, Public, returns correct post-back value though.
Controller Postback code
[HttpPost]
public ActionResult Create(GoldSetnUsers newGS)
{
if (ModelState.IsValid)
{ // newGS gets me value
}
}
View
#model mvc2db.Models.GoldSetnUsers
#using BootstrapSupport;
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#Html.BeginControlGroupFor(model=>model.Public)
#Html.LabelFor(model => model.Public,new {#class="control-label"})
<div class="controls">
#Html.EditorFor(model => model.Public,new {#class="input-xlarge"})
#Html.ValidationMessageFor(model => model.Public,null,new{#class="help-inline"})
</div>
<div class="controls">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Reviewer</th>
<th>Editor</th>
</thead>
<tbody>
#foreach (var item in Model.gsUsers) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.EditorFor(modelItem => item.isEditor)
</td>
<td>
#Html.EditorFor(modelItem => item.isReviewer)
</td>
</tr>
}
</tbody>
</table></div>
#Html.EndControlGroup()
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save changes</button>
<button class="btn">Cancel</button>
</div>
</fieldset>
}
I guess since you are generating the checkboxes using a foreach loop all the checkboxes will have the same id. Hence there will be an ambiguity so as to which is checked and which is not.
You can try giving the username as the id of the checkbox.