Checkbox list values empty when ModelState is not valid and ASP.NET Core does return Page() - asp.net-core

I created an ASP.NET Core 3.1 project. I have a form in it with several checkbox lists. I can get the values into the properties in POST and they are correctly filled in (e.g. List SelectedItems). However for some custom fields I have to do a validation in OnPost() method and if the conditions are not met or a ModelState is not valid, it return Page(). Normally I would expect that every property that was filled in in the form is still filled in, but the checkboxes are always empty and not a single one is checked. The other data (radio buttons, textboxes, etc.) are still filled in.
I even tried to put the values within the Razor page, but even then neither of the checkboxes was checked.
Here is an example of one of the checkboxes:
In Razor page:
#for (var i = 1; i <= 10; i++){
<input name="AreChecked" type="checkbox" id="#i" value="#i" /> #i<br />
<input type="hidden" value="true" id="#i" name="AreChecked" />}
Behind code:
[BindProperties]
public class TestFormModel : PageModel
{
[BindProperty]
public List<int> AreChecked { get; set; }}
public IActionResult OnPost()
{
//some other form check statements here
//...
if (ModelState.IsValid)
{
//process data code...
}
return Page();
}
Can someone help me with this?

You could use JQuery to achieve as shown :
#page
#model RazorPages3_1.AddimgModelModel
<div class="row">
<div class="col-md-4">
<form enctype="multipart/form-data" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Petimg.PetName" class="control-label"></label>
<input asp-for="Petimg.PetName" class="form-control" />
<span asp-validation-for="Petimg.PetName" class="text-danger"></span>
</div>
<div class="form-group">
<input asp-for="Uploads" class="form-control" />
</div>
#for (var i = 1; i <= 10; i++)
{
<input name="AreChecked" type="checkbox" id="#i" value="#i" /> #i<br />
<input type="hidden" value="true" id="#i" name=""AreChecked" />
}
<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 {
<script>
var checkedlist = #Html.Raw(Json.Serialize(Model.AreChecked));;
if (checkedlist.length > 0) {
$.each(checkedlist, function (index, value) {
$('input[type=checkbox]').each(function () {
var id = $(this).attr("id");
if (id == value) {
$(this).attr('checked', 'checked');
}
})
});
}
</script>
}
Result

Related

In my creation process I want to write to another entity than only the used

If I submit the page the first save goes without a problem
Than I assigned all values to the other entity which I want to write to create there a new record.
Why do I get an System Null Reference. I have in all fields the values which I want?
[
=== here is my c# Code ===========
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WorkCollaboration.Data;
using WorkCollaboration.Models;
namespace WorkCollaboration.Pages.TimeReports
{
public class CreateModel : PageModel
{
private readonly WorkCollaboration.Data.WorkCollaborationContext _context;
public CreateModel(WorkCollaboration.Data.WorkCollaborationContext context)
{
_context = context;
}
public IActionResult OnGet()
{
CusContactDropDownDisp = _context.CusContactDropDown.ToList(); // Added for DropDown
SupContactDropDownDisp = _context.SupContactDropDown.ToList(); // Added for DropDown
return Page();
}
[BindProperty]
public TimeReport TimeReport { get; set; }
public IEnumerable<Models.CusContactDropDown> CusContactDropDownDisp { get; set; }
public IEnumerable<Models.SupContactDropDown> SupContactDropDownDisp { get; set; }
public Models.PointsforSupContact PointsforSupContact { get; set; }
// To protect from overposting attacks, 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();
}
TimeReport.TimeReportSupContactPointValue = (TimeReport.TimeReportHours * 10);
_context.TimeReport.Add(TimeReport);
await _context.SaveChangesAsync();
//============================================
// Adding new Point Record to Supplier Contact
//============================================
PointsforSupContact.PointsId = TimeReport.TimeReportId;
PointsforSupContact.PointsSupContactId = TimeReport.TimeReportSupplierTalentContactId;
PointsforSupContact.PointsInternalUserId = 1; // User 1 Christof Oberholzer must be entered in Contacts and User
PointsforSupContact.PointsDate = TimeReport.TimeReportDate;
PointsforSupContact.PointsTotal = TimeReport.TimeReportSupContactPointValue;
PointsforSupContact.PointsText = TimeReport.TimeReportText;
PointsforSupContact.PointsTitle = "TimeReporting Points";
_context.PointsforSupContact.Add(PointsforSupContact);
await _context.SaveChangesAsync();
return RedirectToPage("/TimeReportOverview/Index");
}
}
}
==== My Page ======
#page
#using Microsoft.AspNetCore.Localization
#using Microsoft.AspNetCore.Mvc.Localization
#model WorkCollaboration.Pages.TimeReports.CreateModel
#{
ViewData["Title"] = "Create";
ViewData["RandomId"] = Guid.NewGuid().GetHashCode();
}
#inject IViewLocalizer Localizer
<h1>Create</h1>
<h4>TimeReport</h4>
<p>
<a asp-page="/TimeReportOverview/Index">Back to Index</a>
</p>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="TimeReport.TimeReportSupContactPointValue" value="0"/>
<div class="form-group">
<label asp-for="TimeReport.TimeReportId" class="control-label"></label>
<input asp-for="TimeReport.TimeReportId" value='#ViewData["RandomId"]' readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportCustomerNeedContactId" class="control-label"></label>
</div>
<select id="CusContactId" asp-for="CusContactDropDownDisp" asp-items="#(new SelectList(Model.CusContactDropDownDisp,"CusContactId","CusFullName"))">
<option value="" selected disabled>--Choose Customer--</option>
</select>
<div class="form-group">
<input asp-for="TimeReport.TimeReportCustomerNeedContactId" readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportCustomerNeedContactId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportSupplierTalentContactId" class="control-label"></label>
</div>
<select id="SupContactId" asp-for="SupContactDropDownDisp" asp-items="#(new SelectList(Model.SupContactDropDownDisp,"SupContactId","SupFullName"))">
<option value="" selected disabled>--Choose Supplier--</option>
</select>
<div class="form-group">
<input asp-for="TimeReport.TimeReportSupplierTalentContactId" readonly="readonly" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportSupplierTalentContactId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportDate" class="control-label"></label>
<input type="datetime-local" asp-for="TimeReport.TimeReportDate" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportHours" class="control-label"></label>
<input asp-for="TimeReport.TimeReportHours" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportHours" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="TimeReport.TimeReportText" class="control-label"></label>
<input asp-for="TimeReport.TimeReportText" class="form-control" />
<span asp-validation-for="TimeReport.TimeReportText" class="text-danger"></span>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TimeReport.TimeReportState, htmlAttributes: new { #class = "form-group" })
<div class="form-group">
#Html.DropDownListFor(model => model.TimeReport.TimeReportState, new List<SelectListItem>
{
new SelectListItem {Text = "Gebucht", Value = "Reported", Selected = true },
new SelectListItem {Text = "Kontrolliert", Value = "Controlled" },
new SelectListItem {Text = "Verrechnet / Noch nicht bezahlt", Value = "Invoiced / Not yet payed" },
new SelectListItem {Text = "Verrechnet / Bezahlt", Value = "Invoiced / Payed" },
}, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TimeReport.TimeReportState, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
Back to List
</div>
</form>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
$("#CusContactId").on("change", function () {
$("#TimeReport_TimeReportCustomerNeedContactId").val($("#CusContactId").val());
});
$("#SupContactId").on("change", function () {
$("#TimeReport_TimeReportSupplierTalentContactId").val($("#SupContactId").val());
});
</script>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Thank you for your help
First In your view:
ViewData["RandomId"] = Guid.NewGuid().GetHashCode();
GetHashCodemethod make the Guid to int,please make sure it matches the type in your model.
Then the right way to add new PointsforSupContact is to create a new PointsforSupContact,so you need to delete the code:
public Models.PointsforSupContact PointsforSupContact { get; set; }
and change you code to:
//...
await _context.SaveChangesAsync();
//add this line
var PointsforSupContact=new PointsforSupContact();
PointsforSupContact.PointsId = TimeReport.TimeReportId;
//...

Insert ForEach Value in View into the Database MVC

Hi currently I am doing a shopping cart for my project
I would like to ask how can I import the values in a ForEach to the database.
For example, I have the following data in my view.
#foreach (Cart_Has_Services c in Model)
{
<div class="cart-row">
<div class="cart-items">#c.Cart_Service</div>
<div class="cart-items">#c.Additional_Notes</div>
<div class="cart-items">#c.Unit_Price</div>
<div class="cart-items">
<form asp-controller="Cart" asp-action="UpdateCart" formaction="post">
<input type="number" class="item-quantity-input" value="#c.Quantity" />
<input type="submit" class="btn btn-secondary" value="Update" />
</form>
</div>
<div class="cart-items">
<a asp-controller="Cart"
asp-action="DeleteItem"
asp-route-id="#c.Cart_Id"
onclick="return confirm('Delete Serivce #c.Cart_Service')">
Delete
</a>
</div>
</div>
}
As for now, I want to INSERT data (Cart Service, Additional Notes and Quantity) into my database (Order).
In my controller:
public IActionResult Checkout(Cart_Has_Services cart)
{
List<Cart_Has_Services> carts = DBUtl.GetList<Cart_Has_Services>("SELECT * FROM Cart");
string sql = #"INSERT INTO [Order](Order_Name,Order_Description,Order_Quantity)
VALUES('{0}','{1}',{2})";
int ord = DBUtl.ExecSQL(sql, cart.Cart_Service, cart.Additional_Notes, cart.Quantity);
if (ord == 1)
{
TempData["Message"] = "Perofrmance Successfully Created";
TempData["MsgType"] = "success";
return RedirectToAction("Success");
}
else
{
ViewData["Message"] = DBUtl.DB_Message;
ViewData["MsgType"] = "danger";
return View("ShoppingCart");
}
}
I tried the method that I have inserted but it created without inserting the data.
How can I solve this problem?
Hope can get some guidance.
Thank you
The form in the view only submit Quantity, without Cart_Service and Additional_Notes.
To submit their value, you may set hidden inputs in the form. Also you should set name attribute for the input for model binding.
#foreach (Cart_Has_Services c in Model)
{
<div class="cart-row">
<div class="cart-items">#c.Cart_Service</div>
<div class="cart-items">#c.Additional_Notes</div>
<div class="cart-items">#c.Unit_Price</div>
<div class="cart-items">
<form asp-controller="Cart" asp-action="UpdateCart" formaction="post">
<input type="hidden" name="Cart_Service" value="#c.Cart_Service" />
<input type="hidden" name="Additional_Notes" value="#c.Additional_Notes" />
<input type="number" name="Quantity" class="item-quantity-input" value="#c.Quantity" />
<input type="submit" class="btn btn-secondary" value="Update" />
</form>
</div>
<div class="cart-items">
<a asp-controller="Cart"
asp-action="DeleteItem"
asp-route-id="#c.Cart_Id"
onclick="return confirm('Delete Serivce #c.Cart_Service')">
Delete
</a>
</div>
</div>
}

ASP .Net MVC Core binds wrong value in model list

I have a model with the following
- ModelData: List<ModelData>
With ModelData has the following:
- Name (string)
- LanguageId: Guid
And ViewBag has the following:
- Languages: IEnumerable<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>
And the view has the following:
#for (int i = 0; i < Model.ModelData.Count; i++)
{
<div class="row">
<div class="form-group">
<label asp-for="ModelData[i].LanguageId" class="control-label"></label>
<select asp-for="ModelData[i].LanguageId" asp-items="#ViewBag.Languages" class="form-control">
</select>
<span asp-validation-for="ModelData[i].LanguageId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ModelData[i].Name" class="control-label"></label>
<input asp-for="ModelData[i].Name" class="form-control" />
<span asp-validation-for="ModelData[i].Name" class="text-danger"></span>
</div>
#if (i > 0)
{
<div class="col-md-4">
<div class="form-group">
<button name="RemoveDataItem" value="#i.ToString()" class="btn btn-primary">Remove</button>
</div>
</div>
}
</div>
}
<input type="submit" name="AddDataItem" value="Add Item" class="btn btn-primary" />
<input type="submit" value="Create" class="btn btn-primary" />
And the controller as the following:
public async Task<IActionResult> CreateAsync(CreateModel model, string addDataItem, string removeDataItem)
{
if (addDataItem != null)
{
await FillViewBag();
model.ModelData.Add(new ModelData());
return View(model);
}
else if (removeDataItem != null)
{
await FillViewBag();
int itemIndex = int.Parse(removeDataItem);
model.ModelData.RemoveAt(itemIndex);
return View(model);
}
if (!ModelState.IsValid)
{
await FillViewBag();
return View(model);
}
// Save
}
And it works great, however I have a problem as the following:
Let's say i pressed the add button two times so now I have three records on ModelData and I entered a value in all textboxes and selected values in all select list, then I pressed remove next to the second row, so it goes to the controller action, the method removes the data of the correct index, and returns to the view, so Now I should find two rows, first with the data that was entered in the first row, and second with the data that was entered in the third row (because the second row is removed), however, what actually happens is that I end up with the data of the first two rows not the first and the third.
Any help is appreciated considering I did the following:
I validated that the item that is removed is the corect one (the second item), but the value is not bound correctly.
I added this attribute to the textbox value="#Model.ModelData[i].Name", and it worked correctly but I think this is not the correct way to solve this issue, also I did not find a similar attribute for the select tag.
Edit:
I also managed to add static Id for the input fields of each row, but it didn't help
Edit:
The problem is that the index is changed after the second row is removed, so the index of the third row (originally was 2) became 1 after removing the second row, and thus it now has the previous name attribute of second row "ModelData[1].Name" and not "ModelData[2].Name" and I think this is the problem which makes the browser keeps the previous value of the second row
For anyone who is concerned, I found the solution to this issue which is to add the following line before returning the view:
ModelState.Clear();
add index value to each item:
<input type="hidden" name="ModelData.index" value="#i">
update your view code like this:
#for (int i = 0; i < Model.ModelData.Count; i++)
{
<div class="row">
<input type="hidden" name="ModelData.index" value="#i">
<div class="form-group">
<label asp-for="ModelData[i].LanguageId" class="control-label"></label>
<select asp-for="ModelData[i].LanguageId" asp-items="#ViewBag.Languages" class="form-control">
</select>
<span asp-validation-for="ModelData[i].LanguageId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ModelData[i].Name" class="control-label"></label>
<input asp-for="ModelData[i].Name" class="form-control" />
<span asp-validation-for="ModelData[i].Name" class="text-danger"></span>
</div>
#if (i > 0)
{
<div class="col-md-4">
<div class="form-group">
<button name="RemoveDataItem" value="#i.ToString()" class="btn btn-primary">Remove</button>
</div>
</div>
}
</div>
}
Where's your source data? What you have done is just change the model parmeter.
Also, I can reproduce your problem, when I directly return View after remove the specify record. It can be fixed by using RedirectToAction
I made a demo based on your codes, you can refer to the below codes:
Controller:
public static CreateModel createModel = new CreateModel
{
ModelDatas = new List<ModelData>
{
new ModelData{ LanguageId = 1, Name = "a"},
new ModelData{ LanguageId = 2, Name = "b"},
new ModelData{ LanguageId = 3, Name = "c"}
}
};
public IActionResult Create()
{
FillViewBag();
return View(createModel);
}
[HttpPost]
public IActionResult Create(CreateModel model, string addDataItem, string removeDataItem)
{
if (addDataItem != null)
{
FillViewBag();
createModel.ModelDatas.Add(new ModelData());
return RedirectToAction("Create");
}
else if (removeDataItem != null)
{
FillViewBag();
int itemIndex = int.Parse(removeDataItem);
createModel.ModelDatas.RemoveAt(itemIndex);
return RedirectToAction("Create");
}
if (!ModelState.IsValid)
{
FillViewBag();
return RedirectToAction("Create");
}
return View();
}
View:
#model CreateModel
<form asp-action="Create" asp-controller="Test" method="post">
#for (int i = 0; i < Model.ModelDatas.Count; i++)
{
<div class="row">
<div class="form-group">
<label asp-for="ModelDatas[i].LanguageId" class="control-label"></label>
<select asp-for="ModelDatas[i].LanguageId" asp-items="#ViewBag.Languages" class="form-control">
</select>
<span asp-validation-for="ModelDatas[i].LanguageId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ModelDatas[i].Name" class="control-label"></label>
<input asp-for="ModelDatas[i].Name" class="form-control" />
<span asp-validation-for="ModelDatas[i].Name" class="text-danger"></span>
</div>
#if (i >= 0)
{
<div class="col-md-4">
<div class="form-group">
<button name="RemoveDataItem" value="#i.ToString()" class="btn btn-primary">Remove</button>
</div>
</div>
}
</div>
}
<input type="submit" name="AddDataItem" value="Add Item" class="btn btn-primary" />
<input type="submit" value="Create" class="btn btn-primary" />
</form>
Result:

Setting properties using asp-for in MVC Core App with EF Core?

As I understand it from these docs: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-3.1 , asp-for is used to transfer values from input elements to backend C# class properties, for example:
<input type="text" id="wsite" name="wsite" maxlength="11" asp-for="WebsiteName">
Along with '#folderName ClassName;' at the top, lets you transfer to this example property:
public string WebsiteName { get; set; }
However, testing this out with console.WriteLine show that the property is still null after the form containing the input has been submitted. Any idea what I'm missing?
Edit: Updated to show my property name and asp-for value match, and to add my controller:
[HttpPost]
public IActionResult Post()
{
DBCRUD.Initialize(_context);
return NoContent();
}
The asp-for tag should match the variable-name.
Try defining your html-form like:
#model Classname
<form asp-action="ActionName" asp-controller="ControllerName" ...>
<input type="text" asp-for="VarName">
and your controller:
public MyReturnVariable ActionName(ClassName class) {
Console.WriteLine(class.VarName);
}
The Tag Helpers is used with Model binding and creating and rendering HTML elements(display the model properties) in the web page.
So, in the Web page (or view page), at the top of the header, we should add the following code to assign the model.
#model MVCSample.Models.BookModel
Then, using the following code to display the properties:
<div class="row">
<div class="col-md-4">
<form asp-action="AddBook">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ID" class="control-label"></label>
<input asp-for="ID" class="form-control" />
<span asp-validation-for="ID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="bookName" class="control-label"></label>
<input asp-for="bookName" class="form-control" />
<span asp-validation-for="bookName" class="text-danger"></span>
</div>
<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">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Code in the controller:
[HttpGet]
public IActionResult AddBook()
{
BookModel book = new BookModel()
{
ID = 1001,
bookName = "War and Peace",
Title = "War and Peace"
};
return View(book);
}
Code in the model:
public class BookModel
{
public int ID { get; set; }
public string bookName { get; set; }
public string Title { get; set; }
}
More details information, you could check the Model Binding.

Why is the Bind attribute seemingly breaking my model binding of nested objects?

Could someone help me resolve this issue. I'm trying to limit over posting with bind param action but it seems that it doesn't work at all. When I removed the Bind keyword, everything started to work as a charm.
Here is the code sample:
View Model:
public class ProductCreateViewModel
{
public Product Product { get; set; }
public ICollection<IFormFile> Images { get; set; }
}
Action:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Product.Id,Product.CategoryId,Product.Description,Product.Title")] ProductCreateViewModel productVM)
{
if (ModelState.IsValid)
{
_context.Add(productVM.Product);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewData["CategoryId"] = new SelectList(_context.Categories.Include(c => c.Categories).Where(c => c.ParentCategoryId == null), "Id", "Name", productVM.Product.CategoryId);
return View(productVM);
}
View:
#model CatalogWebApp.Models.ProductsViewModels.ProductCreateViewModel
#{
ViewData["Title"] = "Add Product";
ViewData["BigPageTitle"] = "Products";
ViewData["PageBoxTitle"] = "Add New Product";
}
<form asp-action="Create">
<div class="form-horizontal">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Product.CategoryId" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select name="Product.CategoryId" class ="form-control">
#foreach(Category item in (ViewBag.CategoryId as SelectList).Items)
{
<option value="#item.Id">#item.Name</option>
if (item.Categories != null && item.Categories.Count > 0)
{
foreach (var subCat in item.Categories)
{
<option value="#subCat.Id">--#subCat.Name</option>
}
}
}
</select>
</div>
</div>
<div class="form-group">
<label asp-for="Product.Description" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Product.Description" class="form-control" />
<span asp-validation-for="Product.Description" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="Product.Title" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Product.Title" class="form-control" />
<span asp-validation-for="Product.Title" class="text-danger" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Could someone pelase indicate if I have a problem or it is only a known asp.net core issue?
I'm not quite sure why you using Bind for your case.
Just create sepatate ViewModel with only properties you need like ProductCreateStort.
Then use this ViewModel in your controller signature and inherit your main model from it.
This way you won't mess with Bind and limit your params on POST
While I'm fairly new to ASP.NET Core myself (and coming to this question 7 months late), I ran into this same issue. I think the key here is that you have to bind "Product" for it to be considered. Binding "Product.Id" by itself doesn't appear to be good enough. So this should work:
[Bind("Product,Product.Id,Product.CategoryId,Product.Description,Product.Title")]
Of course, Hamid Mosalla's comment is a better option if ALL of your bound properties are on the nested object (which leads to wonder why you need a view model in the first place). In my case, I have a nested object AND a local property, so using the "Prefix" solution wasn't the right thing to do.
Anyway, hope this helps someone.
You need to pass your values as params string[], not as a single string separated by commas:
[Bind("Product.Id","Product.CategoryId","Product.Description","Product.Title")]
See Source