【问题标题】:ModelState.IsValid is false for sending the Id with hidden inputModelState.IsValid 对于发送带有隐藏输入的 Id 为 false
【发布时间】:2021-08-23 20:47:44
【问题描述】:

我刚开始学习 asp.net core razor pages 并使用教程构建一个简单的项目。 这个项目有一个用于编辑书籍的“编辑”剃须刀页面。我正在尝试将我的模型(Book)的 ID 传递给带有隐藏输入的 post 处理程序,因为没有它 Book.Id 将为 0。但是当我使用 asp-for 标签助手并点击更新时提交按钮,Model.IsValid 为 false。 但是当在“编辑”页面中我可以看到 URL 中的值时,这本书的 ID 是通过“索引”页面中的 URL 传递的。 这是我的模型:

    public class Book
    {
        [Key]
        public int Id { get; set; }
        [Required]
        public string Title { get; set; }

        public string Author { get; set; }

        public string ISBN { get; set; }
     
     }

还有我用于编辑的 cshtml:

    <h2 class="text-info">Edit Book</h2>

<div class="container border m-3">
    <form method="post">
        <input asp-for="Book.Id" type="hidden"/>
        <div class="row form-group mt-2">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <label for="title" class="col-sm-2 col-form-label " asp-for="Book.Title"></label>
            <div class="col-sm-6">
                <input asp-for="Book.Title" class="form-control" id="title"/>
                <span asp-validation-for="Book.Title" class="text-danger"></span>
            </div>
        </div>
        <div class="row form-group mt-2">
            <label for="author" class="col-sm-2 col-form-label " asp-for="Book.Author"></label>
            <div class="col-sm-6">
                <input asp-for="Book.Author" class="form-control" id="author"/>
                <span asp-validation-for="Book.Author" class="text-danger"></span>

            </div>
        </div>
        <div class="row form-group mt-2">
         <label for="ISBN" class="col-sm-2 col-form-label " asp-for="Book.ISBN"></label>
        <div class="col-sm-6">
            <input asp-for="Book.ISBN" class="form-control" id="ISBN"/>
                <span asp-validation-for="Book.ISBN" class="text-danger"></span>

        </div>
    </div>
    <div class="row ">
        <div class="col-3 offset-2">
            <input type="submit" value="Update" class="btn btn-primary form-control"/>
        </div>
        <div class="col-3 ">
            <a asp-page="Index" class="btn btn-secondary form-control">Back To List</a>
        </div>
    </div>
</form>
@section scripts{
    <partial name="_ValidationScriptsPartial" />
}

还有我的cshtml.cs:

public class EditModel : PageModel
{
    private readonly ApplicationDbContext _db;

    public EditModel(ApplicationDbContext db)
    {
        _db = db;
    }

    [BindProperty] 
    public Book Book { get; set; }

    public async Task OnGet(int id)
    {
        await _db.Book.FindAsync(id);
    }

    public async Task<IActionResult> OnPost()
    {
        if (ModelState.IsValid)
        {
            var bookFromDb = await _db.Book.FindAsync(Book.Id);
            bookFromDb.Title = Book.Title;
            bookFromDb.Author = Book.Author;
            bookFromDb.ISBN = Book.ISBN;

            await _db.SaveChangesAsync();
            return RedirectToPage("Index");

        }

        return RedirectToPage();

    }


}

【问题讨论】:

  • 在您的 OnGet 中,您没有将 Book 属性设置为您的 db 调用的结果。加载页面时如何没有出现空异常?这可能是问题吗?
  • @MajdOdeh 我认为这是因为在索引页面中,当我点击“编辑”按钮时,它会通过“asp-route-id”标签助手传递 ID:a asp-page="Edit" asp-route-id="@t.Id" class="btn btn-success text-white btn-sm"&gt;Edit Book&lt;/a&gt;

标签: c# asp.net asp.net-core


【解决方案1】:

但是这本书的 ID 是通过“索引”页面中的 URL 传递的 在“编辑”页面中,我可以看到 URL 中的值。

PageModel 中的

Book 只会绑定来自一个来源的数据。所以它不会绑定查询字符串中的数据。

第一种方式,如果Book.Id使用隐藏输入,则需要设置Book的值。然后Book.Id 将具有值,否则在发布时它是空字符串。如下更改:

public async Task OnGet(int id)
{
    Book = await _db.Book.FindAsync(id);
}

另一种方式,你可以像OnGet方法一样设置id作为参数,然后将id设置为Book.Id

public async Task<IActionResult> OnPost(int id)
{
    Book.Id = id;
    //...
    return RedirectToPage();
}

这样,Book.Id 的隐藏输入就没用了:

<input asp-for="Book.Id" type="hidden" />

【讨论】:

  • 感谢您的回答,但我完全按照讲师在教程中所做的操作。在每本书的索引页面上都有一个带有锚标记的“编辑”按钮,如下所示:a asp-page="Edit" asp-route-id="@t.Id" class="btn btn-success text-white btn-sm"&gt;Edit Book&lt;/a&gt; 这样,ID 将通过 URL 传递到“编辑”页面。然后在“编辑”页面的 OnPost 处理程序中,他通过此 ID 带有隐藏输入,因此 ID 不为 0。但是当我这样做时,StateModel.Isvalid 变为 false。
  • 当然不是。您误解了模型绑定和标签助手。 asp-route-id="@t.Id" 只是在剃须刀页面的 url 中生成查询字符串。它不会将值绑定到输入。绑定输入值的正确方法是在 OnGet 方法中设置Book 值。
  • 本教程所做的应该是我回答的第一种方式。你错过了Book = await _db.Book.FindAsync(id);。你可以看看教程。我确信通过这样的asp-route-id 绑定输入值是不可能的。
  • 是的,这就是问题所在,但这不是一个好的错误:\感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 2020-08-10
  • 2018-02-16
  • 2013-08-18
  • 2019-05-20
  • 2016-03-13
  • 2012-06-26
  • 1970-01-01
  • 2019-12-22
相关资源
最近更新 更多