在.net core中通过viewmodel传递列表项

发布于 2025-01-14 02:12:48 字数 5976 浏览 0 评论 0原文

我对此很陌生,这对某些人来说可能很容易。 我正在努力连接视图和控制器之间的特定字段(下拉列表项)。我假装是将一个类别(来自列表)与一个产品相关联。

对于这个特定的控制器,我的系统作为模型、服务和视图模型。

对于产品类别,我有以下代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文