选定的下拉值如何从视图组件保存到主模型?
How does selected dropdown value get saved from View Component to main model?
ASP.NET Core 5 MVC 网络应用程序。问题是它是如何工作的,而不是为什么它不工作。我不了解该机制,所以不想看到它在将来因一些“快乐的手指”编码事故而失败...
我有一个控制器期望创建的主模型:
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
只有您的典型记录保存字段)。
我有一个视图组件模型;我需要两个,每个下拉菜单一个,所以你可以很容易地想象另一个,修改名称以保护无辜者...:[=28=]
类别:
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>
所有作品和下拉列表都已填写。我可以 select 两个选项。现在是未知部分。
关于 Create
的 POST
方法:
[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);
}
断点将显示 CategoryId
和 ProductId
的正确 selected 值。
所以问题是,这个工作是不是因为 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 核心中的模型绑定根据 name
进行匹配。如果名称匹配,则相应的属性将绑定到模型。
在您的 ViewComponent 中,您的代码(model => model.CategoryId
):
@Html.DropDownListFor(model => model.CategoryId, new SelectList(Model.Categories, "Id", "Name"), new { @class = "form-control" })
会在生成的html代码中给出name =CategoryId
那么CategoryId
这个名字也在你的ProductCategory
模型中,如果他们的名字匹配,则绑定成功。
ASP.NET Core 5 MVC 网络应用程序。问题是它是如何工作的,而不是为什么它不工作。我不了解该机制,所以不想看到它在将来因一些“快乐的手指”编码事故而失败...
我有一个控制器期望创建的主模型:
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
只有您的典型记录保存字段)。
我有一个视图组件模型;我需要两个,每个下拉菜单一个,所以你可以很容易地想象另一个,修改名称以保护无辜者...:[=28=]
类别:
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>
所有作品和下拉列表都已填写。我可以 select 两个选项。现在是未知部分。
关于 Create
的 POST
方法:
[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);
}
断点将显示 CategoryId
和 ProductId
的正确 selected 值。
所以问题是,这个工作是不是因为 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 核心中的模型绑定根据 name
进行匹配。如果名称匹配,则相应的属性将绑定到模型。
在您的 ViewComponent 中,您的代码(model => model.CategoryId
):
@Html.DropDownListFor(model => model.CategoryId, new SelectList(Model.Categories, "Id", "Name"), new { @class = "form-control" })
会在生成的html代码中给出name =CategoryId
那么CategoryId
这个名字也在你的ProductCategory
模型中,如果他们的名字匹配,则绑定成功。