Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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">[email protected]</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?

like image 365
NiL Avatar asked Mar 10 '23 14:03

NiL


1 Answers

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

like image 91
teo van kot Avatar answered Apr 28 '23 05:04

teo van kot