I send a request to the web service and the response that I get is a list of names and values. I loop them in the view and render a form, to allow users to fill the fields and submit it. But the viewmodel always returns null in post action.
this is my View:
<form method="post">
<div class="row register-form">
#foreach (var item in Model.FlowOutputModel)
{
<div class="col-md-6">
<div class="form-group">
<label for="#item.CharacteristicValue">
#item.CharacteristicName:
</label>
<input asp-for="#item.CharacteristicValue" type="text"
class="form-control"
placeholder="#item.CharacteristicName *" value="" required/>
</div>
</div>
}
<div class="col-md-12">
<input type="submit" class="btnRegister" value="Submit"/>
</div>
</div>
</form>
my model as followin:
public class DecisionInputModel
{
public string FlowName { get; set; }
public List<FlowOutputModel> FlowOutputModel { get; set; }
}
public class FlowOutputModel
{
public string CharacteristicName { get; set; }
public string CharacteristicValue { get; set; }
}
My Controller
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(DecisionInputModel decisionInput)
{
if (ModelState.IsValid)
{
_service.GetResults(decisionInput);
}
}
Any suggestions?
replace loop foreach by for and add action to form
<form method="post" action="#Url.Action("Index", "Home")">
<input asp-for="#Model.FlowName" type="text" class="form-control" />
// or maybe even better
#Html.TextBoxFor(model => model.FlowName, new { #class = "form-control" })
<div class="row register-form">
#for(int i=0; i < Model.FlowOutputModel.Count; i++)
{
<div class="col-md-6">
<div class="form-group">
<label for="#Model.FlowOutputModel[i].CharacteristicValue">
#Model.FlowOutputModel[i].CharacteristicName:
</label>
<input asp-for="#Model.FlowOutputModel[i].CharacteristicValue" type="text"
class="form-control"
placeholder="#Model.FlowOutputModel[i].CharacteristicName *" value="" required/>
</div>
</div>
}
<div class="col-md-12">
<input type="submit" class="btnRegister" value="Submit"/>
</div>
</div>
</form>
You have to add the "name" attribute to the input:
<input name="FlowOutputModel[#Model.FlowOutputModel.IndexOf(item)].CharacteristicValue" type="text" class="form-control" placeholder="#item.CharacteristicName *" value="" required />
Related
I try make a library Sistem where in category to book has a relation many to many i need put in my book edit view a partial view frow the entity, could someone help-me?
my edit view:
#model MVC_Library.Models.Book
#{
ViewData["Title"] = "Edit";
BookCategory teste = ViewBag.testeview;
}
<h1>Edit</h1>
<h4>Book</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="BookId" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Author" class="control-label"></label>
<input asp-for="Author" class="form-control" />
<span asp-validation-for="Author" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublishDate" class="control-label"></label>
<input asp-for="PublishDate" class="form-control" />
<span asp-validation-for="PublishDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BasePrice" class="control-label"></label>
<input asp-for="BasePrice" class="form-control" />
<span asp-validation-for="BasePrice" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Quantity" class="control-label"></label>
<input asp-for="Quantity" class="form-control" />
<span asp-validation-for="Quantity" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublishingCompanyId" class="control-label"></label>
<select asp-for="PublishingCompanyId" class="form-control" asp-items="ViewBag.PublishingCompanyId"></select>
<span asp-validation-for="PublishingCompanyId" class="text-danger"></span>
</div>
<div>
#Html.Partial("_EditBookCategory", teste)
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
my partial view that work (but in this way just pre-select one category item)
#model MVC_Library.Models.BookCategory
<div class="row">
<div class="col-md-12">
<label asp-for="CategoryId" class="control-label"></label>
<select multiple asp-for="CategoryId" class="form-control" name = "BookCategory[]" asp-items="ViewBag.SelectedCategory"></select>
</div>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
and my controller edit part
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var book = await _context.Books.FindAsync(id);
if (book == null)
{
return NotFound();
}
List<BookCategory> bookCategory = _context.BookCategories.Where(e => e.BookId == id).ToList();
ViewData["PublishingCompanyId"] = new SelectList(_context.PublishingCompanies, "PublishingCompanyId", "PublishingCompanyName", book.PublishingCompanyId);
//this is what i try for try return mutiple category select (don't work with this viewbag)
/* ViewBag.SelectedCategory = new MultiSelectList(_context.Categories.ToList(), "CategoryId", "CategoryName", bookCategory); */
//this viewbag return only one category selected but work
ViewBag.testeview = bookCategory.First();
return View(book);
}
Just once selected (the first), but a want to return all. Need help if this could possible.
If you want to display all the related categories selected:
Be sure asp-for="CategoryId" here CategoryId should be type of int[] or string[]. Or just remove asp-for tag helper, because you have added name="BookCategory[]" here, it will override asp-for generated name attribute. When you form submit, your action always need contain a parameter named BookCategory[], no matter you add asp-for or not.
Besides BookCategory[] is not a correct name with no index in array, it should be BookCategory or any other name and the parameter name in action should be type of int[] or string[]. Guessing you may want to match the selected value to List model BookCategory's CategoryId. It is not acceptable for multiple select.
Be sure the last parameter in MultiSelectList should be int[] or string[]. From your code, the dataValueField in MultiSelectList matches CategoryId property, so your last parameter should be something like bookCategory.Select(a=>a.CategoryId).ToList().
ViewBag.SelectedCategory = new MultiSelectList(_context.Categories.ToList(), "CategoryId", "CategoryName",
bookCategory.Select(a=>a.CategoryId).ToList());
No need use ViewBag.testeview, just change like below:
#Html.Partial("_EditBookCategory", new BookCategory())
Whole working demo should be like:
Model:
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public DateTime PublishDate { get; set; }
public int BasePrice { get; set; }
public int Quantity { get; set; }
public int PublishingCompanyId { get; set; }
public List<BookCategory> BookCategory { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public List<BookCategory> BookCategory { get; set; }
}
public class BookCategory
{
public int CategoryId { get; set; }
public int BookId { get; set; }
public Category Category { get; set; }
public Book Book { get; set; }
}
View:
#model Book
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Book</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="BookId" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Author" class="control-label"></label>
<input asp-for="Author" class="form-control" />
<span asp-validation-for="Author" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublishDate" class="control-label"></label>
<input asp-for="PublishDate" class="form-control" />
<span asp-validation-for="PublishDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BasePrice" class="control-label"></label>
<input asp-for="BasePrice" class="form-control" />
<span asp-validation-for="BasePrice" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Quantity" class="control-label"></label>
<input asp-for="Quantity" class="form-control" />
<span asp-validation-for="Quantity" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PublishingCompanyId" class="control-label"></label>
<select asp-for="PublishingCompanyId" class="form-control" asp-items="ViewBag.PublishingCompanyId"></select>
<span asp-validation-for="PublishingCompanyId" class="text-danger"></span>
</div>
<div>
//change here....
#Html.Partial("_EditBookCategory", new BookCategory())
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Partial View:
#model BookCategory
<div class="row">
<div class="col-md-12">
<label asp-for="CategoryId" class="control-label"></label>
<select multiple class="form-control" name="CategoryId" asp-items="ViewBag.SelectedCategory"></select>
</div>
</div>
Controller:
Note: I just hard-coded the data due to easy testing, it is the same with your get data from database. You just need change like what my comment said, other code is no need change like what I did.
public IActionResult Edit(int? id)
{
var book = new Book()
{
BookId = 1,
PublishDate = DateTime.Now,
Author = "a1",
BasePrice = 34,
PublishingCompanyId = 1,
Quantity = 23,
Title = "aa"
};
List<BookCategory> bookCategory = new List<BookCategory>()
{
new BookCategory(){BookId=1,CategoryId=1},
new BookCategory(){BookId=2,CategoryId=1},
new BookCategory(){BookId=2,CategoryId=3}
};
ViewData["PublishingCompanyId"] = new List<SelectListItem>() {
new SelectListItem() { Value = "1", Text = "Elementos1" },
new SelectListItem() { Value = "2", Text = "Elementos2" },
new SelectListItem() { Value = "3", Text = "Elementos3" }
};
var c = new List<Category>()
{
new Category(){CategoryId=1,Name="aa"},
new Category(){CategoryId=2,Name="bb"},
new Category(){CategoryId=3,Name="cc"}
};
//change here....
ViewBag.SelectedCategory = new MultiSelectList(c, "CategoryId", "Name", bookCategory.Select(a=>a.CategoryId).ToList());
//ViewBag.testeview = bookCategory.First();
return View(book);
}
[HttpPost]
public IActionResult Edit(int? id,Book book, int[] CategoryId)
{
//do your stuff......
return View();
}
Result:
For how to choose multiple option, you just need press Ctrl key meanwhile click the option.
This question already has answers here:
Values of disabled inputs will not be submitted
(9 answers)
Closed 1 year ago.
I am trying to learn how to pass data into an HttpPost function in Asp.Net Core MVC using tag helpers.
Here is my Model:
public class PersonModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool Exists { get; set; }
}
Here is my View:
<form asp-controller="Home" asp-action="CustomerInput" method="post">
<div class="row">
<div class="col">
<div class="form-group">
<label for="lblId">
Id
</label>
<input asp-for="#Model.Id" type="text" class="form-control" id="lblId" disabled>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label for="lblName">
Name
</label>
<input asp-for="#Model.Name" type="text" class="form-control" id="lblId" disabled>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<div class="form-check">
<input asp-for="#Model.Exists" class="form-check-input" type="checkbox" id="chkExists">
<label class="form-check-label" for="chkExists">
Exists
</label>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<input type="submit" name="btnNext" value="Next" class="btn btn-secondary" />
</div>
</div>
</div>
Here is my Controller:
[HttpGet]
public IActionResult CustomerInput()
{
var model = new PersonModel { Id = 1, Name = "Homer Simpson", Exists = false };
return View(model);
}
[HttpPost]
public IActionResult CustomerInput(PersonModel model)
{
return View("CustomerOutput", model);
}
When I attempt to submit the form and pass the model to my HttpPost function, only the Exists value passes successfully. Id is always 0 and Name is always null.
What am I missing?
Disabled inputs won't post back to the controller. Use readonly:
<input asp-for="#Model.Id" type="text" class="form-control" id="lblId" readonly>
See devlin carnate's post for clarity
It's also good practice to use unique identifiers for your input id's!
I've created a model that has its own class:
public class VMRequest()
{
public int Id { get; set; }
public List<Slot> Slots { get; set; }
public class Slot()
{
public DateTime Date { get; set; }
}
}
Then let's say I add five Slots to the list, they show perfectly in a View if I do it like this:
<form asp-action="Request">
<div class="row flex-column">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
#foreach (var slot in Model.Slots)
{
<div class="col-md-6">
<div class="form-group">
<label asp-for="#slot.Date" class="control-label"></label>
<input asp-for="#slot.Date" type="date" class="form-control" />
<span asp-validation-for="#slot.Date" class="text-danger"></span>
</div>
</div>
}
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</div>
</form>
But then on submission, even though the VMRequest model is passed to the controller, the changes on the view controls don't pass - I have no idea how to pin identifiers to each of the controls??
I'm sure this is possible!?
Change your code to:
#for(int x = 0; x < Model.Slots.Length;x++)
{
<div class="col-md-6">
<div class="form-group">
<label asp-for="#Model.Slots[x].Date" class="control-label"></label>
<input asp-for="#Model.Slots[x].Date" type="date" class="form-control" />
<span asp-validation-for="#Model.Slots[x].Date" class="text-danger"></span>
</div>
</div>
}
Then the form posted back will be correct.
Each element needs to be named with an index to bind back to the model. There is a great example at https://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/.
In Short:
Using a razor component within a for loop should handle this for you like:
for (int i = 0; i < 3; i++)
#Html.TextBoxFor(m => m[i].Title)
#Html.TextBoxFor(m => m[i].Author)
#Html.TextBoxFor(m => m[i].DatePublished)
}
I'm not understanding how to properly bind a single item from a collection. In my project, a student can have multiple plans with these models:
public class Student
{
public Student()
{
Plans = new HashSet<Plan>();
}
public int StudentId { get; set; }
public string Designee { get; set; }
public string DesigneePhone { get; set; }
public virtual ICollection<Plan> Plans { get; set; }
}
public partial class Plan
{
public int PlanId { get; set; }
public int StudentId { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual Student Student { get; set; }
}
I'm listing each plan with its own Save button on the page. I thought I was using the asp-for helper correctly according to this Learn Razor Pages post.
#page "{studentId:int}"
#model CollectionTest.PlansModel
<form asp-page-handler="SaveMain" method="post">
<div class="row mt-3">
<input type="hidden" asp-for="Student.StudentId" />
<div class="col">
<label asp-for="Student.Designee"></label>
<input asp-for="Student.Designee" class="form-control" />
</div>
<div class="col">
<label asp-for="Student.DesigneePhone"></label>
<input asp-for="Student.DesigneePhone" class="form-control" />
</div>
<div class="col-auto align-self-end">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
</form>
<hr />
#for (int i = 0; i < Model.Student.Plans.Count(); i++)
{
var planId = Model.Student.Plans.ToList()[i].PlanId.ToString();
<div id="#("card_Plan" + planId)" class="card">
<div class="card-header">
<h5>Plan ##planId</h5>
</div>
<div class="card-body">
<form id="#("form_Plan" + planId)" asp-page-handler="SavePlan" method="post">
<input type="hidden" asp-for="Student.Plans.ToList()[i].PlanId" />
<div class="row">
<div class="col">
<label asp-for="Student.Plans.ToList()[i].StartDate"></label>
<input asp-for="Student.Plans.ToList()[i].StartDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].StartDate"></span>
</div>
<div class="col">
<label asp-for="Student.Plans.ToList()[i].EndDate"></label>
<input asp-for="Student.Plans.ToList()[i].EndDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].EndDate"></span>
</div>
</div>
</form>
</div>
<div class="card-footer">
<div class="float-right">
<button type="submit" class="btn btn-primary" form="#("form_Plan" + planId)">Save</button>
</div>
</div>
</div>
}
But it seems like nothing is being bound in the SavePlan page handler:
[BindProperty]
public Student Student { get; set; }
.
.
.
public async Task<IActionResult> OnPostSavePlan(int planId)
{
if (!ModelState.IsValid)
{
return Page();
}
/******************************
*
* Student.Plans is empty and planId is zero
*
*******************************/
Plan plan = await _planContext.Plan.FirstAsync(p => p.PlanId == planId);
_planContext.Attach(plan).State = EntityState.Modified;
try
{
await _planContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PlanExists(plan.PlanId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Plans");
}
What am I doing wrong?
According to your code, because what you pass in the razor page is [0].PlanId, but what you receive in the OnPostSavePlan method is planId. If you only need to receive planId, you need to change the form.
<div class="card-body">
<form id="#("form_Plan" + planId)" asp-page-handler="SavePlan" method="post">
<input type="hidden" asp-for="#planId" />
From your requirement,it seems you want to pass a list of plans. So you need to modify your code in the following steps:
Plans.cshtml:
<form id="form_Plan" asp-page-handler="SavePlan" method="post">
#for (int i = 0; i < Model.Student.Plans.Count(); i++)
{
var planId = Model.Student.Plans.ToList()[i].PlanId.ToString();
<div id="#("card_Plan" + planId)" class="card">
<div class="card-header">
<h5>Plan ##planId</h5>
</div>
<div class="card-body">
<input type="hidden" asp-for="Student.Plans.ToList()[i].PlanId" />
<div class="row">
<div class="col">
<label asp-for="Student.Plans.ToList()[i].StartDate"></label>
<input asp-for="Student.Plans.ToList()[i].StartDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].StartDate"></span>
</div>
<div class="col">
<label asp-for="Student.Plans.ToList()[i].EndDate"></label>
<input asp-for="Student.Plans.ToList()[i].EndDate" class="form-control" />
<span asp-validation-for="Student.Plans.ToList()[i].EndDate"></span>
</div>
</div>
</div>
</div>
}
<div class="card-footer">
<div class="float-right">
<button type="submit" class="btn btn-primary" form="form_Plan">Save</button>
</div>
</div>
</form>
Plans.cshtml.cs:
public class PlansModel : PageModel
{
public IActionResult OnGet()
{
//for easy testing,I add the data manually
Student = new Student()
{
Plans = new List<Plan>()
{
new Plan(){ PlanId=1, StartDate=DateTime.Parse("2019-8-7")},
new Plan(){ PlanId=2, StartDate=DateTime.Parse("2019-4-7")},
new Plan(){ PlanId=3, StartDate=DateTime.Parse("2019-6-7")}
}
};
return Page();
}
[BindProperty]
public Student Student { get; set; }
public async Task<IActionResult> OnPostSavePlan(List<Plan> plans)
{
//...
}
}
Result:
Update:
Plans.cshtml:
#foreach (var plan in Model.Student.Plans)
{
var planId = plan.PlanId.ToString();
<div id="#("card_Plan" + planId)" class="card">
<div class="card-header">
<h5>Plan ##planId</h5>
</div>
<div class="card-body">
<form id="#("form_Plan" + planId)" asp-page-handler="SavePlan" method="post">
<input type="hidden" asp-for="#plan.PlanId" />
<div class="row">
<div class="col">
<label asp-for="#plan.StartDate"></label>
<input asp-for="#plan.StartDate" class="form-control" />
<span asp-validation-for="#plan.StartDate"></span>
</div>
<div class="col">
<label asp-for="#plan.EndDate"></label>
<input asp-for="#plan.EndDate" class="form-control" />
<span asp-validation-for="#plan.EndDate"></span>
</div>
</div>
</form>
</div>
<div class="card-footer">
<div class="float-right">
<button type="submit" class="btn btn-primary" form="#("form_Plan" + planId)">Save</button>
</div>
</div>
</div>
}
Plans.cshtml.cs:
public async Task<IActionResult> OnPostSavePlan(Plan plan)
{
//...
}
Result:
I have a ViewModel named CreateRoleViewModel which contains the items shown below. On the view, I'm iterating through a list of permissions and displaying them. What I'm trying to accomplish is to allow a user to create a new role and add permissions to that role. I've been able to successfully pass all data to the controller except the permissions. Hopefully I'm not confusing anyone. I've tried to use a for loop (which did't produce correct results) and a foreach loop, which did produce the correct results (meaning displayed all permissions currently available). I realize I'm going to also, most likely need to update my domain model for Permissions to include columns for View, Modify etc.
CreateViewModel
public class CreateRoleViewModel
{
[Required]
public string RoleName { get; set; }
public string RoleDescription { get; set; }
public List<Permissions> Permissions { get; set; }
public bool AllowViewAccess { get; set; }
public bool AllowModifyAccess { get; set; }
public CreateRoleViewModel()
{
Permissions = new List<Permissions>();
}
}
PermissionsController
[Route("Administration/Permissions/CreateRole")]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateRole(CreateRoleViewModel newRole)
{
try
{
var test = newRole;
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
View
<form method="post" asp-action="CreateRole">
<div class="form-group col-6" style="padding-left:0">
<label asp-for="RoleName"></label>
<input asp-for="RoleName" class="form-control" />
<span asp-validation-for="RoleName" class="text-danger"></span>
</div>
<div class="form-group col-6" style="padding-left:0">
<label asp-for="RoleDescription"></label>
<input asp-for="RoleDescription" class="form-control" />
</div>
<div class="form-group ">
<h4>Permissions</h4>
<div class="card">
<div class="card-header">
<input type="checkbox" class="form-check-input p-2" id="selectAll">
<label class="form-check-label" for="selectAll">Select All<span style="font-weight:bold;font-style:italic;"> (This will allow read/write access to ALL selected items.)</span></label>
</div>
</div>
<!--Permissions should go here-->
<div class="card-body border">
#foreach (var item in Model.Permissions)
{
<div class="row" style="border-radius:3px;border-top:2px solid gray;border-bottom:2px solid gray;padding:15px;">
<div class="col-8">
<input type="checkbox" class="form-check-input p-2" id="select">
<label class="form-check-label" for="select" style="font-weight:bold;">#item.PermissionName</label>
<p style="color:gray;">#item.PermissionDescription</p>
</div>
<div class="col-2">
<input type="checkbox" class="form-check-input p-2" id="readOnly" asp-for="AllowViewAccess">
<label class="form-check-label" for="readOnly">View</label>
</div>
<div class="col-2">
<input type="checkbox" class="form-check-input p-2" id="readWrite" asp-for="AllowModifyAccess">
<label class="form-check-label" for="readWrite">Modify</label>
</div>
</div>
}
</div>
<div asp-validation-summary="All" class="text-info"></div>
<button style="background-color: #6987D5;color:white;" class="btn">Save</button>
<button class="btn" style="background-color:lightgray;border:1px solid darkgray">Cancel</button>
</div>
</form>
From your description and the view code, I think you should put the "AllowViewAccess " and "AllowModifyAccess " in the Permissions class, because the role have separate "View" or "Modify" access to different permissions. Based on your codes, I made an example:
Model:
public class CreateRoleViewModel
{
[Required]
public string RoleName { get; set; }
public string RoleDescription { get; set; }
public List<Permissions> Permissions { get; set; }
public CreateRoleViewModel()
{
Permissions = new List<Permissions>();
}
}
public class Permissions
{
public string PermissionName { get; set; }
public string PermissionDescription { get; set; }
public bool AllowViewAccess { get; set; }
public bool AllowModifyAccess { get; set; }
}
View:
#model CreateRoleViewModel
#{
var i = 0;
}
<form method="post" asp-action="CreateRole">
<div class="form-group col-6" style="padding-left:0">
<label asp-for="RoleName"></label>
<input asp-for="RoleName" class="form-control" />
<span asp-validation-for="RoleName" class="text-danger"></span>
</div>
<div class="form-group col-6" style="padding-left:0">
<label asp-for="RoleDescription"></label>
<input asp-for="RoleDescription" class="form-control" />
</div>
<div class="form-group ">
<h4>Permissions</h4>
<div class="card">
<div class="card-header">
<input type="checkbox" class="form-check-input p-2" id="selectAll">
<label class="form-check-label" for="selectAll">Select All<span style="font-weight:bold;font-style:italic;"> (This will allow read/write access to ALL selected items.)</span></label>
</div>
</div>
<!--Permissions should go here-->
<div class="card-body border">
#foreach (var item in Model.Permissions)
{
<div class="row" style="border-radius:3px;border-top:2px solid gray;border-bottom:2px solid gray;padding:15px;">
<div class="col-8">
<input type="checkbox" class="form-check-input p-2" id="select">
<input type="hidden" asp-for="#Model.Permissions[i].PermissionName">
<label class="form-check-label" for="select" style="font-weight:bold;">#item.PermissionName</label>
<p style="color:gray;">#item.PermissionDescription</p>
<input type="hidden" asp-for="#Model.Permissions[i].PermissionDescription">
</div>
<div class="col-2">
<input type="checkbox" class="form-check-input p-2" id="readOnly" asp-for="#Model.Permissions[i].AllowViewAccess">
<label class="form-check-label" for="readOnly">View</label>
</div>
<div class="col-2">
<input type="checkbox" class="form-check-input p-2" id="readWrite" asp-for="#Model.Permissions[i].AllowModifyAccess">
<label class="form-check-label" for="readWrite">Modify</label>
</div>
</div>
i++;
}
</div>
<div asp-validation-summary="All" class="text-info"></div>
<button style="background-color: #6987D5;color:white;" class="btn">Save</button>
<button class="btn" style="background-color:lightgray;border:1px solid darkgray">Cancel</button>
</div>
</form>
Controller:
public IActionResult Index()
{
CreateRoleViewModel createRoleViewModel = new CreateRoleViewModel();
return View(createRoleViewModel);
}
//[Route("Administration/Permissions/CreateRole")]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateRole(CreateRoleViewModel newRole)
{
try
{
var test = newRole;
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
Result: