You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC中Inventory.cshtml无法与控制器及模型交互求助

ASP.NET Core MVC中Inventory视图无法与控制器/模型交互的问题

我在ASP.NET Core MVC项目里,Inventory.cshtml视图没法接收或发送数据到控制器和模型。已经排查了拼写、命名空间这类可能的错误,但控制台和终端都没报错,根本找不到问题所在。核心问题是:Inventory.cshtml收不到来自模型和控制器的错误提示或消息。

注:项目用了Shared文件夹下的_DashboardLayout和_Layout两种布局,不确定会不会影响。


相关代码

实体类Product.cs

using System.ComponentModel.DataAnnotations;

namespace SportsCapstone.Entities
{
    public class Product
    {
        [Key]
        public int Id { get; set; }
        // public byte[] Image { get; set; } // Storing image as byte array
        [Required(ErrorMessage = "Product is required.")]
        [MaxLength(20, ErrorMessage = "Max 20 characters allowed")]
        public string ProductName { get; set; }
        [Required(ErrorMessage = "Brand is required.")]
        [MaxLength(20, ErrorMessage = "Max 20 characters allowed")]
        public string ProductBrand { get; set; }
        [Required(ErrorMessage = "Quantity should not be empty")]
        [Range(1, int.MaxValue, ErrorMessage = "Quantity Must be atleast 1.")]
        public int Quantity { get; set; }
        [Required(ErrorMessage = "Type of Product is required.")]
        [MaxLength(20, ErrorMessage = "Max 20 characters allowed")]
        public string TypeOfProduct { get; set; }
        [Required(ErrorMessage = "Type of Age is required.")]
        [Range(1, 60, ErrorMessage = "Age should not be more than 60")]
        public string AgeRange { get; set; }
    }
}

模型类InventoryItem.cs

using System.ComponentModel.DataAnnotations;

namespace SportsCapstone.Models
{
    public class InventoryItem
    {
        [Required(ErrorMessage = "Product name is required.")]
        [MaxLength(20, ErrorMessage = "Max 20 characters allowed.")]
        public string ProductName { get; set; }

        [Required(ErrorMessage = "Product brand is required.")]
        [MaxLength(20, ErrorMessage = "Max 20 characters allowed.")]
        public string ProductBrand { get; set; }

        [Required(ErrorMessage = "Quantity is required.")]
        [Range(1, int.MaxValue, ErrorMessage = "Quantity must be a positive number.")]
        public int Quantity { get; set; } // Changed to int

        [Required(ErrorMessage = "Type of product is required.")]
        [MaxLength(20, ErrorMessage = "Max 20 characters allowed.")]
        public string TypeOfProduct { get; set; }

        [Required(ErrorMessage = "Age range is required.")]
        [Range(5, 20, ErrorMessage = "Age range must be between 5 and 20.")]
        public string AgeRange { get; set; }

        // [Required(ErrorMessage = "Image is required.")]
        // public IFormFile Image { get; set; } // For file uploads
    }
}

控制器InventoryController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SportsCapstone.Models; // This should be your models namespace
using SportsCapstone.Entities; // Keep if you need to reference Product
using Microsoft.EntityFrameworkCore;

namespace SportsCapstone.Controllers // Corrected namespace
{
    [Authorize]
    public class InventoryController : Controller
    {
        private readonly AppDbContext _dbContext;
        public InventoryController(AppDbContext appDbContext)
        {
            _dbContext = appDbContext;
        }

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

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Inventory(InventoryItem model) // Change to InventoryItem
        {
            if (ModelState.IsValid)
            {
                // If needed, convert InventoryItem to Product here
                Product product = new Product
                {
                    ProductName = model.ProductName,
                    ProductBrand = model.ProductBrand,
                    Quantity = model.Quantity,
                    TypeOfProduct = model.TypeOfProduct,
                    AgeRange = model.AgeRange
                };

                try
                {
                    _dbContext.Products.Add(product);
                    _dbContext.SaveChanges();
                    ModelState.Clear();
                    ViewBag.Message = $"{product.ProductName} registered successfully. Please Login.";
                }
                catch (DbUpdateException)
                {
                    ModelState.AddModelError("", "Please enter a unique Email or Password.");
                    return View(model);
                }
                return View();
            }
            return View("Inventory", model); //return model with correct view name
        }
    }
}

视图Inventory.cshtml(关键部分)

@model SportsCapstone.Models.InventoryItem
@{
    Layout = "_DashboardLayout";
}

...

@if (ViewBag.Message != null)
{
    <div class="d-flex align-items-center justify-content-center w-100" style="color: green">
        @ViewBag.Message
    </div>
}
<form asp-controller="Inventory" asp-action="Create" method="post" class="inv-cp-ppqty">
    <div class="image">
        <label for="imageUpload">
            <svg id="imageLabel" width="16" height="16" viewBox="0 0 16 16" fill="none"
                xmlns="http://www.w3.org/2000/svg">

            </svg>
            <img id="imagePreview"
                style="display: none; max-width: 100%; height:100%; object-fit: cover; border-radius: 10px;" />
        </label>
        @* <input asp-for="Image" type="file" id="imageUpload" name="Image" required
        onchange="previewImage(event)" /> *@

        @* <span asp-validation-for="Image" class="text-danger"></span> *@

        @* <img src="" alt=""> *@
    </div>
    <div class="fill-inv">
        <div class="inp-inv">
            <input asp-for="ProductName" type="text" placeholder="Product Name" />
            <span asp-validation-for="ProductName" class="text-danger"></span>

        </div>
        <div class="inp-inv">
            <input asp-for="ProductBrand" type="text" placeholder="Product Brand" />
            <span asp-validation-for="ProductBrand" class="text-danger"></span>
        </div>
        <div class="inp-inv">
            <input asp-for="Quantity" type="number" placeholder="Quantity" min="1" />
            <span asp-validation-for="Quantity" class="text-danger"></span>
        </div>
        <div class="inp-inv">
            <select asp-for="TypeOfProduct" id="typeOfProduct" class="form-control">
                <option value="" disabled selected> Type of Product </option>
                <option value="Cloth"> Cloth </option>
                <option value="Pants"> Pants </option>
                <option value="Accessories"> Accessories </option>
                <option value="SportsGear"> Sports Gear </option>
                <!-- Add more options as needed -->
            </select>
            <span asp-validation-for="TypeOfProduct" class="text-danger"></span>

        </div>
        <div class="inp-inv">
            <select asp-for="AgeRange" id="ageRange" class="form-control">
                <option value="" disabled selected> Age </option>
                <option value="Kids"> -18 </option>
                <option value="Adults"> 18+ </option>
                <!-- Add more options as needed -->
            </select>
            <span asp-validation-for="AgeRange" class="text-danger"></span>

        </div>
        <button type="submit" class="button-type">
            <h5> Create Item </h5>
        </button>
    </div>
</form>

问题排查与修复方案

1. 表单Action匹配错误

视图表单指定了asp-action="Create",但控制器中只有名为Inventory的Post方法,不存在Create方法,导致表单提交后找不到对应Action,无任何反馈。

修复:将表单的asp-action改为"Inventory":

<form asp-controller="Inventory" asp-action="Inventory" method="post" class="inv-cp-ppqty">

2. 字符串属性错误使用Range验证

Product和InventoryItem中的AgeRange是字符串类型,但都添加了仅适用于数值类型的[Range]注解,导致验证逻辑失效,甚至引发隐性模型绑定错误。

修复:移除字符串属性上的[Range]注解,若需限制取值范围,改用[RegularExpression]:

// 修改InventoryItem.cs的AgeRange属性
[Required(ErrorMessage = "Age range is required.")]
[RegularExpression(@"^(Kids|Adults)$", ErrorMessage = "Age range must be 'Kids' or 'Adults'")]
public string AgeRange { get; set; }

// 修改Product.cs的AgeRange属性
[Required(ErrorMessage = "Type of Age is required.")]
public string AgeRange { get; set; }

3. 保存成功后错误清空ModelState

控制器中保存成功后调用ModelState.Clear(),会清空所有模型状态,且返回无模型的View(),导致视图无法获取输入值或错误信息。同时使用ViewBag传递消息易丢失,推荐用PRG模式防止重复提交。

修复:保存成功后重定向到Get方法,用TempData传递消息:

try
{
    _dbContext.Products.Add(product);
    _dbContext.SaveChanges();
    TempData["Message"] = $"{product.ProductName} registered successfully.";
    return RedirectToAction(nameof(Inventory));
}
catch (DbUpdateException)
{
    ModelState.AddModelError("", "保存失败,请检查输入是否合法或重复。");
    return View(model);
}

视图中修改消息显示逻辑:

@if (TempData["Message"] != null)
{
    <div class="d-flex align-items-center justify-content-center w-100" style="color: green">
        @TempData["Message"]
    </div>
}

4. Get方法未传递空模型

控制器的Get方法Inventory()直接返回View(),未传递空的InventoryItem模型,可能导致asp-for标签无法正确生成name属性,影响模型绑定。

修复:返回带空模型的视图:

public IActionResult Inventory()
{
    return View(new InventoryItem());
}

5. 布局页缺失验证脚本

若_DashboardLayout未引用ASP.NET Core客户端验证脚本,会导致客户端验证失效,服务器端错误也可能无法正常显示。

修复:在布局页</body>前添加验证脚本:

<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

内容的提问来源于stack exchange,提问作者Leonhard Meinhard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:02:02