如何将选定的下拉值从视图组件保存到主模型?

问题描述

ASP.NET Core 5 MVC Web 应用程序。问题是它是如何工作的,而不是它为什么不工作。我不明白这个机制,所以不想看到它在未来因为一些“快乐的手指”编码事故而失败......

我有一个控制器期望创建的主模型:

public class ProductCategory : BaseClass
{
    public int ProductId { get; set; }
    public virtual Product Product { get; set; }

    public int CategoryId { get; set; }
    public virtual Category Category { get; set; }
}

BaseClass 只是典型的记录保存字段。

我有一个视图组件模型;我需要两个,每个下拉菜单一个,所以你可以很容易地想象另一个修改名称以保护无辜者......:

类别:

public class CategoryList
{
    public CategoryList()
    {
        Categories = new List<Category>();
    }

    public int CategoryId { get; set; }

    [displayName("Categories")]
    public List<Category> Categories { get; set; }
}

类别视图组件:

public class CategoryDropdownViewComponent : ViewComponent
{
    private readonly ApplicationDbContext _db;

    public CategoryDropdownViewComponent(ApplicationDbContext context)
    {
        _db = context;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        var items = await GetCategoriesAsync();
        var TheView = "Default";
        var list = new CategoryList();

        if (items.Count == 0)
        {
            TheView = "CategoryMaintenanceLink";
        }
        else
        {
            items.Insert(0,new Category() { Id = 0,Name = "-- Please select an option --" });
            list.Categories = items;
        }

        return View(TheView,list);
    }

    private Task<List<Category>> GetCategoriesAsync()
    {
        return _db.Category.ToListAsync();
    }
}

以及类别的认视图(我将其存储在 ~\Shared\Components\CategoryDropdown\ 中):

@model CoolestProjectNameEver.Models.CategoryList

<p>
    @Html.DropDownListFor(model => model.CategoryId,new SelectList(Model.Categories,"Id","Name"),new { @class = "form-control" })
</p>

所以,在我的控制器中,我开始创建:

    public IActionResult Create()
    {
        return View();
    }

Create 视图中,我启动了视图组件:

        <div class="form-group">
            <label asp-for="ProductId" class="control-label"></label>
            @await Component.InvokeAsync("ProductDropdown")
        </div>
        <div class="form-group">
            <label asp-for="CategoryId" class="control-label"></label>
            @await Component.InvokeAsync("CategoryDropdown")
        </div>

所有作品和下拉列表都已填满。我可以为两者选择选项。现在是未知部分。

转到 POSTCreate 方法

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(ProductCategory productCategory)
    {
        try
        {
            if (ModelState.IsValid)        <--- breakpoint
            {
                _context.Add(productCategory);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        return View(productCategory);
    }

断点将显示CategoryIdProductId 选择的正确值。

所以问题是,这是否因为 VC 模型中的名称与主控制器模型匹配而起作用,并且它以某种方式自动填充?

1如果我的 ViewComponent 模型有,说 SelectedValueId 而不是 CategoryId,那么它会因为不匹配而失败?

2 异步 ViewComponent单独模型的值是如何在回发时插入主模型的?

解决方法

事实上,如果您将 Create 视图代码更改为:

  <div class="form-group">
        @await Component.InvokeAsync("ProductDropdown")
    </div>
    <div class="form-group">
        @await Component.InvokeAsync("CategoryDropdown")
    </div>

它也会成功绑定。

asp.net core 中的模型绑定根据name进行匹配。如果名称匹配,则将相应的属性绑定到模型。

在您的 ViewComponent 中,您的代码 (model => model.CategoryId):

 @Html.DropDownListFor(model => model.CategoryId,new SelectList(Model.Categories,"Id","Name"),new { @class = "form-control" })

将在生成的 html 代码中给出 name =CategoryId enter image description here

那么名称 CategoryId 也在您的 ProductCategory 模型中,如果它们的名称匹配,则绑定将成功。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...