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

ASP.NET Core中HTML输入无法绑定到模型的问题求助

问题描述

我正在尝试创建一个Order实体,已经完成了模型、控制器和视图的编写,但在视图中填写所有必填内容后,数据无法传递到Post方法,ModelState.IsValid始终返回false,报错提示「(字段名称) 不能为空」。尝试过创建独立视图模型、更换视图中的@model等方法,卡了两天,求解决。

控制器代码

using FindWorkWeb.DataAccess.Data;
using FindWorkWeb.Models.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;

namespace FindWorkWeb.Areas.User.Controllers
{
    [Area("User")]
    public class OrderController : Controller
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly ApplicationDbContext _context;

        public OrderController(UserManager<IdentityUser> userManager, ApplicationDbContext context)
        {
            _userManager = userManager;
            _context = context;
        }

        public class InputModel() 
        {
            [Display(Name = "Title")]
            public string Title { get; set; }

            [Display(Name = "Description")]
            public string Description { get; set; }

            [Display(Name = "ApproximatedPrice")]
            public float ApproximatedPrice { get; set; }

            [Display(Name = "City")]
            public string City { get; set; }
        }

        public InputModel Input { get; set; }

        [HttpGet]
        [Authorize]
        public IActionResult Create()
        {
            Input = new InputModel();
            return View(Input);
        }

        [HttpPost]
        public async Task<IActionResult> Create(InputModel inputModel)
        {
            if (ModelState.IsValid)
            {
                var user = await _userManager.GetUserAsync(User);
                var order = new Order
                {
                    ApplicationUserId = user.Id,
                    Title = Input.Title,
                    Description = Input.Description,
                    ApproximatedPrice = Input.ApproximatedPrice,
                    City = Input.City,
                    Status = "Pending",
                    PaymentStatus = false
                };

                _context.Orders.Add(order);
                await _context.SaveChangesAsync();
                return RedirectToAction("Index", "Home");
            }
            return View();
        }
    }
}

视图代码

@model FindWorkWeb.Areas.User.Controllers.OrderController.InputModel

@{
    ViewData["Title"] = "Create Order";
}

<h1>Create Order</h1>

<form asp-action="Create" method="post">
    <div class="form-group">
        
        <input asp-for="Title" class="form-control" placeholder="Title"/>
        @* <span asp-validation-for="InputModel.Title" class="text-danger"></span> *@
    </div>
    <div class="form-group">
        
        <textarea asp-for="Description" class="form-control" placeholder="Description"></textarea>
        @* <span asp-validation-for="Input.Description" class="text-danger"></span> *@
    </div>
    <div class="form-group">
        
        <input asp-for="ApproximatedPrice" class="form-control" placeholder="Price" />
        @* <span asp-validation-for="Input.ApproximatedPrice" class="text-danger"></span> *@
    </div>
    <div class="form-group">
        
        <input asp-for="City" class="form-control" placeholder="City" />
        @* <span asp-validation-for="Input.City" class="text-danger"></span> *@
    </div>
    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

@section Scripts {
    @{
        await Html.RenderPartialAsync("_ValidationScriptsPartial");
    }
}
解决方案

1. 修正InputModel类定义的语法错误

控制器中嵌套的InputModel类多了多余的括号,这会导致编译异常或模型绑定失败:

// 错误写法
public class InputModel() 
// 正确写法
public class InputModel

2. Post方法中使用传入的inputModel参数

控制器的Input是实例属性,Post请求会生成全新的控制器实例,此时Input未被赋值,始终为默认值。正确的做法是使用Post方法接收的inputModel参数来构建Order实体:

var order = new Order
{
    ApplicationUserId = user.Id,
    Title = inputModel.Title,
    Description = inputModel.Description,
    ApproximatedPrice = inputModel.ApproximatedPrice,
    City = inputModel.City,
    Status = "Pending",
    PaymentStatus = false
};

3. 验证失败时返回带模型的View

当ModelState.IsValid为false时,必须将接收的inputModel传递回视图,否则视图会使用空模型,导致用户输入的内容丢失,且验证提示不准确:

// 错误代码
return View();
// 正确代码
return View(inputModel);

4. 启用视图中的验证提示

取消视图中验证提示的注释,并修正asp-validation-for的目标(直接使用属性名,无需前缀),方便查看具体的验证错误:

<span asp-validation-for="Title" class="text-danger"></span>
<span asp-validation-for="Description" class="text-danger"></span>
<span asp-validation-for="ApproximatedPrice" class="text-danger"></span>
<span asp-validation-for="City" class="text-danger"></span>

5. (可选)将InputModel提取为独立类

把嵌套在控制器中的InputModel移到单独的ViewModels文件夹下,代码结构更清晰,也避免视图引用控制器内部类的复杂路径:

namespace FindWorkWeb.ViewModels.User
{
    public class OrderInputModel
    {
        [Display(Name = "Title")]
        [Required(ErrorMessage = "标题不能为空")]
        public string Title { get; set; }

        [Display(Name = "Description")]
        [Required(ErrorMessage = "描述不能为空")]
        public string Description { get; set; }

        [Display(Name = "ApproximatedPrice")]
        [Range(0.01, double.MaxValue, ErrorMessage = "价格必须大于0")]
        public float ApproximatedPrice { get; set; }

        [Display(Name = "City")]
        [Required(ErrorMessage = "城市不能为空")]
        public string City { get; set; }
    }
}

之后控制器和视图只需引用这个独立类即可。


内容的提问来源于stack exchange,提问作者Ulad Shuhayeu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:17:07