在.net core中通过viewmodel传递列表项
我对此很陌生,这对某些人来说可能很容易。 我正在努力连接视图和控制器之间的特定字段(下拉列表项)。我假装是将一个类别(来自列表)与一个产品相关联。
对于这个特定的控制器,我的系统作为模型、服务和视图模型。
对于产品类别,我有以下代码:
public class DryGoodsProduct
{
public int Id { get; set; }
public string ProductName { get; set; }
[Display(Name = "Category")]
[Required]
public DryGoodsCategory DryGoodsCategory { get; set; }
public int DryGoodsCategoryId { get; set; }
public DryGoodsProduct()
{ }
public DryGoodsProduct(int id, string productName, DryGoodsCategory category)
{
Id = id;
ProductName = productName;
DryGoodsCategory = category;
}
}
类别类别如下:
public class DryGoodsCategory
{
public int Id { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
public virtual ICollection<DryGoodsProduct> DryGoodsProducts { get; set; }
public DryGoodsCategory()
{
}
public DryGoodsCategory(int id, string categoryName)
{
Id = id;
CategoryName = categoryName;
}
}
产品服务类别如下:
public class DryGoodsProductService
{
private readonly DB _context;
public DryGoodsProductService(DB context)
{
_context = context;
}
public async Task<List<DryGoodsProduct>> FindAllAsync()
{
return await _context.DryGoodsProducts
.Include(obj => obj.DryGoodsCategory)
.ToListAsync();
}
public async Task InsertAsync(DryGoodsProduct drygoodsProduct)
{
_context.Add(drygoodsProduct);
await _context.SaveChangesAsync();
}
public async Task<DryGoodsProduct> FindByIdAsync(int id)
{
return await _context.DryGoodsProducts
.Include(obj => obj.DryGoodsCategory)
.FirstOrDefaultAsync(x => x.Id == id);
}
public async Task RemoveAsync(int id)
{
try
{
var obj = await _context.DryGoodsProducts.FindAsync(id);
_context.DryGoodsProducts.Remove(obj);
await _context.SaveChangesAsync();
}
catch (IntegrityException e)
{
throw new IntegrityException(e.Message);
}
}
public async Task UpdateAsync(DryGoodsProduct drygoodsProduct)
{
bool hasAny = await _context.DryGoodsProducts.AnyAsync(x => x.Id == drygoodsProduct.Id);
if (!hasAny)
{
throw new NotFoundException("ID não encontrado");
}
try
{
_context.Update(drygoodsProduct);
await _context.SaveChangesAsync();
}
catch (DbConcurrencyException ex)
{
throw new DbConcurrencyException(ex.Message);
}
}
}
>视图模型类是:
public class DryGoodsProductViewModel
{
public DryGoodsProduct drygoodsProduct { get; set; }
public virtual ICollection<DryGoodsCategory> DryGoodsCategories { get; set; }
}
控制器如下:
public async Task<IActionResult> Create()
{
var categories = await _categoryService.FindAllAsync();
var product = new DryGoodsProduct();
var viewmodel = new DryGoodsProductViewModel()
{
drygoodsProduct = product,
DryGoodsCategories = categories,
};
return View(viewmodel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(DryGoodsProduct product)
{
if (ModelState.IsValid)
{
await _productService.InsertAsync(product);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(product);
}
创建视图:
enter @model Library.ViewModels.Logistics.DryGoodsProductViewModel
@{
ViewData["Title"] = "Create";
Layout = "~/Areas/Logistics/Views/Shared/_LogisticsLayout.cshtml"; }
<h1>Create</h1>
<h4>Products</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
@Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="drygoodsProduct.ProductName" class="control-label"></label>
<input asp-for="drygoodsProduct.ProductName" class="form-control" />
<span asp-validation-for="drygoodsProduct.ProductName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="drygoodsProduct.DryGoodsCategoryId" class="control-label"></label>
<select asp-for="drygoodsProduct.DryGoodsCategoryId" asp-items="@(new SelectList(Model.DryGoodsCategories, "Id", "CategoryName"))" class="form-control"></select>
<span asp-validation-for="drygoodsProduct.DryGoodsCategoryId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
所以... 错误说:
处理请求时发生未处理的异常。 InvalidOperationException:传递到的模型项 ViewDataDictionary 的类型 'Library.Models.Logistics.DryGoods.DryGoodsProduct',但是这个 ViewDataDictionary 实例需要类型的模型项 'Library.ViewModels.Logistics.DryGoodsProductViewModel'。
我的意思是,我已经用另一个控制器做了类似的事情,一切都很好。
我希望得到一些关于如何解决这个问题的反馈。
I'm new to this and this might be quite easy for some people.
I'm struggling to connect a particular field (dropdown list item) between a View and a Controller. What I'm pretending is to associate a category (from a list) to a product.
For this particular Controller, my system as a Model, a Service and a ViewModel.
For the product class I have the following code:
public class DryGoodsProduct
{
public int Id { get; set; }
public string ProductName { get; set; }
[Display(Name = "Category")]
[Required]
public DryGoodsCategory DryGoodsCategory { get; set; }
public int DryGoodsCategoryId { get; set; }
public DryGoodsProduct()
{ }
public DryGoodsProduct(int id, string productName, DryGoodsCategory category)
{
Id = id;
ProductName = productName;
DryGoodsCategory = category;
}
}
The category class is the following:
public class DryGoodsCategory
{
public int Id { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
public virtual ICollection<DryGoodsProduct> DryGoodsProducts { get; set; }
public DryGoodsCategory()
{
}
public DryGoodsCategory(int id, string categoryName)
{
Id = id;
CategoryName = categoryName;
}
}
The product service class is the following:
public class DryGoodsProductService
{
private readonly DB _context;
public DryGoodsProductService(DB context)
{
_context = context;
}
public async Task<List<DryGoodsProduct>> FindAllAsync()
{
return await _context.DryGoodsProducts
.Include(obj => obj.DryGoodsCategory)
.ToListAsync();
}
public async Task InsertAsync(DryGoodsProduct drygoodsProduct)
{
_context.Add(drygoodsProduct);
await _context.SaveChangesAsync();
}
public async Task<DryGoodsProduct> FindByIdAsync(int id)
{
return await _context.DryGoodsProducts
.Include(obj => obj.DryGoodsCategory)
.FirstOrDefaultAsync(x => x.Id == id);
}
public async Task RemoveAsync(int id)
{
try
{
var obj = await _context.DryGoodsProducts.FindAsync(id);
_context.DryGoodsProducts.Remove(obj);
await _context.SaveChangesAsync();
}
catch (IntegrityException e)
{
throw new IntegrityException(e.Message);
}
}
public async Task UpdateAsync(DryGoodsProduct drygoodsProduct)
{
bool hasAny = await _context.DryGoodsProducts.AnyAsync(x => x.Id == drygoodsProduct.Id);
if (!hasAny)
{
throw new NotFoundException("ID não encontrado");
}
try
{
_context.Update(drygoodsProduct);
await _context.SaveChangesAsync();
}
catch (DbConcurrencyException ex)
{
throw new DbConcurrencyException(ex.Message);
}
}
}
and the view model class is:
public class DryGoodsProductViewModel
{
public DryGoodsProduct drygoodsProduct { get; set; }
public virtual ICollection<DryGoodsCategory> DryGoodsCategories { get; set; }
}
the controller is the following:
public async Task<IActionResult> Create()
{
var categories = await _categoryService.FindAllAsync();
var product = new DryGoodsProduct();
var viewmodel = new DryGoodsProductViewModel()
{
drygoodsProduct = product,
DryGoodsCategories = categories,
};
return View(viewmodel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(DryGoodsProduct product)
{
if (ModelState.IsValid)
{
await _productService.InsertAsync(product);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(product);
}
and the create view :
enter @model Library.ViewModels.Logistics.DryGoodsProductViewModel
@{
ViewData["Title"] = "Create";
Layout = "~/Areas/Logistics/Views/Shared/_LogisticsLayout.cshtml"; }
<h1>Create</h1>
<h4>Products</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data">
@Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="drygoodsProduct.ProductName" class="control-label"></label>
<input asp-for="drygoodsProduct.ProductName" class="form-control" />
<span asp-validation-for="drygoodsProduct.ProductName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="drygoodsProduct.DryGoodsCategoryId" class="control-label"></label>
<select asp-for="drygoodsProduct.DryGoodsCategoryId" asp-items="@(new SelectList(Model.DryGoodsCategories, "Id", "CategoryName"))" class="form-control"></select>
<span asp-validation-for="drygoodsProduct.DryGoodsCategoryId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
So...
The error says:
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the
ViewDataDictionary is of type
'Library.Models.Logistics.DryGoods.DryGoodsProduct', but this
ViewDataDictionary instance requires a model item of type
'Library.ViewModels.Logistics.DryGoodsProductViewModel'.
I mean, I've done something quit similar with another controller and everything is ok.
I would appreciate some feedback on how to solve this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论