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

ASP.NET Core MVC自定义用户资料编辑功能异常求助(非Identity)

ASP.NET Core MVC 用户资料编辑功能异常(未使用Identity框架)

问题概述

我正在为ASP.NET Core MVC项目添加现有用户资料编辑功能,未使用Identity框架,但功能存在异常,当前报错为Id的验证状态无效(Invalid validation state for Id)。

相关代码

Users模型

public partial class Users
{
    [Key]
    public Guid Id { get; set; }
    [Display(Name = "Name")]
    public string Name { get; set; }

    //email
    [Required(ErrorMessage = "Enter Your Email..")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    //username
    [Required(ErrorMessage = "Enter Username..")]
    [Display(Name = "Username")]
    public string Username { get; set; }

    //password
    [Required(ErrorMessage = "Enter Password...")]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    //confirm
    [Required(ErrorMessage = "Confirm...")]
    [DataType(DataType.Password)]
    [Display(Name = "Confirm Password")]
    [Compare("Password")]
    public string ConfirmPass { get; set; }
}

UsersController控制器

public class UsersController : Controller
{
    private readonly TAContext _context;

    public UsersController(TAContext context)
    {
        _context = context;
    }

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

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

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create([Bind("Id,Name,Email,Username,Password,ConfirmPass")] Users uc) //register users
    {
        _context.Add(uc);
        _context.SaveChanges();
        
        //return RedirectToAction("Edit", "Users");
        return View(uc); //uc?
    }

    [Authorize]
    public async Task<IActionResult> Edit(Guid? id)
    {
        var ucc = await _context.Users.FindAsync(id);

        return View(ucc);
    }

    [HttpPost]
    public async Task<ActionResult> Edit(Guid id, [Bind("Id,Name,Email,Username,Password,ConfirmPass")] Users uc) //register users
    {
        //if (ModelState.IsValid)
        //{
        //    _context.Entry(uc).State = EntityState.Modified;
        //    await _context.SaveChangesAsync();
        //    return RedirectToAction("Index");
        //}

        //_context.Update(uc);
        //await _context.SaveChangesAsync();
 
        //return View(uc);
        if (id != uc.Id)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            try
            {
                _context.Update(uc);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!UserExists(uc.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return RedirectToAction("Login", "Logusers");
        }

        return View(uc);
    }

    private bool UserExists(Guid id)
    {
        return _context.Users.Any(e => e.Id == id);
    }
}

编辑视图

@model TA.Models.Users

@{
    ViewData["Title"] = "Edit";
}
<div class=" container2">
    <hr />
    <h1>User edit</h1>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Edit">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <input type="hidden" asp-for="Id" />
                <div class="form-group">
                    <label asp-for="Name" class="control-label"></label>
                    <input asp-for="Name" class="form-control" placeholder="Name" />
                    <span asp-validation-for="Name" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Username" class="control-label"></label>
                    <input asp-for="Username" class="form-control" placeholder="Username" />
                    <span asp-validation-for="Username" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Password" class="control-label"></label>
                    <input asp-for="Password" class="form-control" type="password" placeholder="Password" />
                    <span asp-validation-for="Password" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="ConfirmPass" class="control-label"></label>
                    <input asp-for="ConfirmPass" class="form-control" type="password" placeholder="Confirm Password" />
                    <span asp-validation-for="ConfirmPass" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Email" class="control-label"></label>
                    <input asp-for="Email" class="form-control" placeholder="Email" />
                    <span asp-validation-for="Email" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Save User Details" class="btn btn-primary" />
                </div>
                <span class="text-danger">@ViewBag.message</span>
            </form>
        </div>
    </div>
    <div>
        <a asp-controller="Home" asp-action="Index" class="return-to-hp">Back to Homepage</a>
    </div>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}  

问题原因分析

  1. 新增用户时Id未正确生成:Guid类型主键默认不会自动生成(除非配置[DatabaseGenerated(DatabaseGeneratedOption.Identity)]),原Create方法未手动生成Guid,导致用户Id可能为空,后续编辑时触发验证错误。
  2. Id字段的不必要验证:编辑时Id作为隐藏字段传递,但ModelState会对Guid类型进行默认验证,路由Id与模型Id匹配时易出现异常。
  3. 密码字段的强制验证:编辑时模型仍保留Password和ConfirmPass的[Required]属性,若用户不想修改密码,空值会触发验证错误,进而影响整体ModelState有效性,间接引发Id的验证提示。

解决方案

1. 修复用户新增时的Id生成

修改Create方法,手动生成Guid并添加ModelState验证:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create([Bind("Name,Email,Username,Password,ConfirmPass")] Users uc)
{
    uc.Id = Guid.NewGuid(); // 生成有效Guid
    if (ModelState.IsValid)
    {
        _context.Add(uc);
        _context.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(uc);
}

2. 移除编辑时Id的验证错误

在Edit的HttpPost方法中,判断ModelState之前手动移除Id的验证条目:

[HttpPost]
[ValidateAntiForgeryToken] // 添加上防CSRF验证
public async Task<IActionResult> Edit(Guid id, [Bind("Id,Name,Email,Username,Password,ConfirmPass")] Users uc)
{
    if (id != uc.Id)
    {
        return NotFound();
    }

    // 移除Id的验证,因为主键无需验证输入
    ModelState.Remove("Id");

    if (ModelState.IsValid)
    {
        try
        {
            _context.Update(uc);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!UserExists(uc.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction("Login", "Logusers");
    }
    return View(uc);
}

3. 优化模型,使用ViewModel分离场景

创建专门的编辑视图模型,移除密码字段的[Required](或根据需求保留),避免不必要的验证:

public class EditUserViewModel
{
    public Guid Id { get; set; }
    [Display(Name = "Name")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Enter Your Email..")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Enter Username..")]
    [Display(Name = "Username")]
    public string Username { get; set; }

    // 仅当允许修改密码时保留,否则可移除
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm Password")]
    [Compare("Password")]
    public string ConfirmPass { get; set; }
}

同时修改视图的@model为TA.Models.EditUserViewModel,并调整控制器中Edit方法的模型绑定逻辑。

内容的提问来源于stack exchange,提问作者Tutorial Hell Veteran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:25:58