.cshtml页面中的ASP-For未使用ASP帮助者验证我的模型

发布于 2025-01-30 10:04:20 字数 4658 浏览 2 评论 0原文

我正在尝试与Bhrugen Patel的YouTube视频一起学习ASP.NET CORE V7预览, https:/// www.youtube.com/watch?v=eru2emiqow0 。在2:04:41,他列出了如何使用“ ASP”助手在将页面提交给服务器之前使用“ ASP”助手来验证用户字段。但是在下面的情况下,我无法触发客户端错误消息。即,我似乎无法针对我的类别模型触发ASP的帮助者,因此,该页面被发送以被服务器验证例程拒绝。这是create.cshtml文件,category.cs class和数据库create ddl:

.cshtml文件:

@page
@model AbbyTrain.Pages.Categories.CreateModel
<div class="container-fluid mt-5">
<form method="post">
    
    <div class="border p-3 mt-4"> 
        <div class="row pb-2"> 
            <h2 class="text-primary pl-3">Create New Category</h2> 
            <hr/>
        </div>
        <div class="mb-3">
            <label asp-for="Category.Name"></label>        
            <input asp-for="Category.Name" class="form-control"/>       
            <span asp-validation-for="Category.Name" class="text-danger"></span> 
        </div>
        <div class="mb-3">
            <label asp-for="Category.DisplayOrder"></label>
            <input asp-for="Category.DisplayOrder" class="form-control"/>
            <span asp-validation-for="Category.DisplayOrder" class="text-danger"></span>        
        </div>
        <div class="mb-3">
            <label asp-for="Category.DateCreated"></label> 
            <input readonly name="Category.DateCreated" class="form-control bg-info"/>
            <span asp-validation-for="Category.DateCreated" class="text-danger"></span>
        </div>
        
        <button type="submit" class="bnt btn-primary" style="width: 150px;">Create</button>
    </div>
</form>
</div>

类别类:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace AbbyTrain.Models
{
    public partial class Category
    {
        public Category()
        {
            ProductCategories = new HashSet<ProductCategories>();
        }
        public int CategoryId { get; set; }
        
        public string Name { get; set; } = null!;
        
        public int DisplayOrder { get; set; }

        public DateTime DateCreated { get; set; }


        public virtual ICollection<ProductCategories> ProductCategories { get; set; }
    }
}

ddl文件,要在sql server中创建类别:

USE [AbbyTrain]
GO

/****** Object:  Table [dbo].[Category]    Script Date: 5/16/2022 5:18:25 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Category](
    [CategoryId] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NOT NULL,
    [DisplayOrder] [int] NOT NULL,
    [DateCreated] [datetime2](7) NOT NULL,
 CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED 
(
    [CategoryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[Category] ADD  DEFAULT (N'') FOR [Name]
GO

per farid的评论,我包括服务器端代码: create.cshtml.cs

public async Task<IActionResult> OnPost()
{
    if (ModelState.IsValid)
    { 
        await _db.Category.AddAsync(Category);
        await _db.SaveChangesAsync();
        return RedirectToPage("Index");
    }
    else

        return RedirectToPage("Create");
}

and and and All Ess都将受到赞赏!

更新了2022-05-18 8:15 UTC

我希望这有助于“慢跑”某人的思想:)

因此,如果我使用数据注释[display =“ name =“ display1 order”)],这有效。但是,如果我使用[必需(errorMessage =“必需的类别名称)”)]这是不起作用的。似乎该模型完全与显示错误消息完全脱节,并且不会通过模型隐式显示或使用数据注释明确显示。

这是我的类别。CS文件,带有数据注释:

namespace AbbyTrain.Models
{
    public partial class Category
    {
        public Category()
        {
            ProductCategories = new HashSet<ProductCategories>();
        }
        [Key]
        public int CategoryId { get; set; }
        [Required(ErrorMessage = "Name is Required")] <--this does not work
        public string Name { get; set; }
        [Required(ErrorMessage = "Display Order is Required")] <--this does not work 
        [Display(Name="Display1 Order")] <--This works
        public int DisplayOrder { get; set; }

        public DateTime DateCreated { get; set; }


        public virtual ICollection<ProductCategories> ProductCategories { get; set; }
    }
}

核心代码中是否有错误?我正在使用预览版本。

I am trying to learn ASP.NET Core v7 preview following along with BHRUGEN Patel's Youtube video https://www.youtube.com/watch?v=eru2emiqow0. At 2:04:41 he lays out how you can validate user fields against the database model using "asp" helpers before the page is submitted to the server. But in the case below, I cannot trigger the client-side error messages. I.e., I can't seem to trigger the asp-for helpers against my Category model and hence, the page is sent on to be rejected by the server validation routine. Here is the Create.cshtml file, the Category.cs class, and the database CREATE DDL:

.cshtml file:

@page
@model AbbyTrain.Pages.Categories.CreateModel
<div class="container-fluid mt-5">
<form method="post">
    
    <div class="border p-3 mt-4"> 
        <div class="row pb-2"> 
            <h2 class="text-primary pl-3">Create New Category</h2> 
            <hr/>
        </div>
        <div class="mb-3">
            <label asp-for="Category.Name"></label>        
            <input asp-for="Category.Name" class="form-control"/>       
            <span asp-validation-for="Category.Name" class="text-danger"></span> 
        </div>
        <div class="mb-3">
            <label asp-for="Category.DisplayOrder"></label>
            <input asp-for="Category.DisplayOrder" class="form-control"/>
            <span asp-validation-for="Category.DisplayOrder" class="text-danger"></span>        
        </div>
        <div class="mb-3">
            <label asp-for="Category.DateCreated"></label> 
            <input readonly name="Category.DateCreated" class="form-control bg-info"/>
            <span asp-validation-for="Category.DateCreated" class="text-danger"></span>
        </div>
        
        <button type="submit" class="bnt btn-primary" style="width: 150px;">Create</button>
    </div>
</form>
</div>

Category class:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace AbbyTrain.Models
{
    public partial class Category
    {
        public Category()
        {
            ProductCategories = new HashSet<ProductCategories>();
        }
        public int CategoryId { get; set; }
        
        public string Name { get; set; } = null!;
        
        public int DisplayOrder { get; set; }

        public DateTime DateCreated { get; set; }


        public virtual ICollection<ProductCategories> ProductCategories { get; set; }
    }
}

DDL File to Create the category in SQL Server:

USE [AbbyTrain]
GO

/****** Object:  Table [dbo].[Category]    Script Date: 5/16/2022 5:18:25 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Category](
    [CategoryId] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NOT NULL,
    [DisplayOrder] [int] NOT NULL,
    [DateCreated] [datetime2](7) NOT NULL,
 CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED 
(
    [CategoryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[Category] ADD  DEFAULT (N'') FOR [Name]
GO

Per Farid's comment I am including the server side code:
Create.cshtml.cs

public async Task<IActionResult> OnPost()
{
    if (ModelState.IsValid)
    { 
        await _db.Category.AddAsync(Category);
        await _db.SaveChangesAsync();
        return RedirectToPage("Index");
    }
    else

        return RedirectToPage("Create");
}

Any and all help is appreciated!

Updated 2022-05-18 8:15 UTC

I hope this helps to "jog" someone's mind :)

So if I use the data annotation [Display(Name="Display1 Order")], this works. But if I use the [Required(ErrorMessage="Category Name is required")] this does not work. It seems like the model is totally disconnected from displaying error messages and does not display implicitly through the model or explicitly using data annotations.

Here is my Category.cs file with data annotations:

namespace AbbyTrain.Models
{
    public partial class Category
    {
        public Category()
        {
            ProductCategories = new HashSet<ProductCategories>();
        }
        [Key]
        public int CategoryId { get; set; }
        [Required(ErrorMessage = "Name is Required")] <--this does not work
        public string Name { get; set; }
        [Required(ErrorMessage = "Display Order is Required")] <--this does not work 
        [Display(Name="Display1 Order")] <--This works
        public int DisplayOrder { get; set; }

        public DateTime DateCreated { get; set; }


        public virtual ICollection<ProductCategories> ProductCategories { get; set; }
    }
}

Is there a bug in the Core code? I am using preview releases.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绮烟 2025-02-06 10:04:20

但是,在下面的情况下,我无法触发客户端错误消息。即,我似乎无法触发ASP的助手,因此我的类别模型?

在讨论您的问题之后,似乎您的modelState验证sub-key在您的验证请求发送到服务器并从中获得响应时,不会被误解。 ModelState.ISVALID来自您的OnPost方法。

如何修复它:

看来,您的模型位置路径就像abbytrain.pages.categories.categories.createmodel,因此问题开始了。它不能与验证子密钥category.name匹配。我认为它与验证子密钥不一样。请在您的环境中检查它。

这是适合您的工作演示:

模型:

public class Category
    {
        [Key]
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
        public int DisplayOrder { get; set; }
        public DateTime DateCreated { get; set; }

    }

视图:

@model DotNet6MVCWebApp.Models.Category
<div class="container-fluid mt-5">
<form asp-controller="Category" asp-action="OnPost" method="post">
    
    <div class="border p-3 mt-4"> 
        <div class="row pb-2"> 
            <h2 class="text-primary pl-3">Create New Category</h2> 
            <hr/>
        </div>
        <div class="mb-3">
            <label asp-for="CategoryName"></label>        
            <input asp-for="CategoryName" class="form-control"/>       
            <span asp-validation-for="CategoryName" class="text-danger"></span> 
        </div>
        <div class="mb-3">
            <label asp-for="DisplayOrder"></label>
            <input asp-for="DisplayOrder" class="form-control"/>
            <span asp-validation-for="DisplayOrder" class="text-danger"></span>        
        </div>
        <div class="mb-3">
            <label asp-for="DateCreated"></label> 
            <input  name="DateCreated" type="date" class="form-control bg-info"/>
            <span asp-validation-for="DateCreated" class="text-danger"></span>
        </div>
        
        <button type="submit" class="bnt btn-primary" style="width: 150px;">Create</button>
    </div>
</form>
</div>

注意:确保您的验证sub key是相同的作为您的ASP-validation-for。您可以在debug模式下在结果视图下检查,如下面的屏幕截图。

控制器:

public async Task<IActionResult> OnPost(Category category)
        {
            if (ModelState.IsValid)
            {
                await _db.Categories.AddAsync(category);
                await _db.SaveChangesAsync();
                return RedirectToPage("Index");
            }
            return View("Index");
        }

输出:

”在此处输入图像说明“

调试步骤:

如何调试模型?或查看它是如何使用数据注释的?

  1. 检查UI代码上的检查元素。
  2. 确保data-valmsg-fornameid属性属性是正确匹配的。
  3. 有关详细信息,请参见下面的屏幕截图

​它应包含以下引用:

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

”输入图像在此处“

” i.sstatic.net/yboqc.png“ alt =”在此处输入图像描述>

您可以参考我们的官方文档有关更多详细信息在这里

But in the case below, I cannot trigger the client-side error messages. I.e., I can't seem to trigger the asp-for helpers against my Category model and hence?

After debugging on your issue, it seems that your ModelState validation sub-key is not getting mactched while your validation request is sending to the server and got the response from ModelState.IsValid from your OnPost method.

How to fix it:

It seems that your model location path is something like AbbyTrain.Pages.Categories.CreateModel so here the problem begins. It cannot match the validation sub key with Category.Name. I think it's not same with the validation sub key. Please check it within your environment.

Here is the working demo for you:

Model:

public class Category
    {
        [Key]
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
        public int DisplayOrder { get; set; }
        public DateTime DateCreated { get; set; }

    }

View:

@model DotNet6MVCWebApp.Models.Category
<div class="container-fluid mt-5">
<form asp-controller="Category" asp-action="OnPost" method="post">
    
    <div class="border p-3 mt-4"> 
        <div class="row pb-2"> 
            <h2 class="text-primary pl-3">Create New Category</h2> 
            <hr/>
        </div>
        <div class="mb-3">
            <label asp-for="CategoryName"></label>        
            <input asp-for="CategoryName" class="form-control"/>       
            <span asp-validation-for="CategoryName" class="text-danger"></span> 
        </div>
        <div class="mb-3">
            <label asp-for="DisplayOrder"></label>
            <input asp-for="DisplayOrder" class="form-control"/>
            <span asp-validation-for="DisplayOrder" class="text-danger"></span>        
        </div>
        <div class="mb-3">
            <label asp-for="DateCreated"></label> 
            <input  name="DateCreated" type="date" class="form-control bg-info"/>
            <span asp-validation-for="DateCreated" class="text-danger"></span>
        </div>
        
        <button type="submit" class="bnt btn-primary" style="width: 150px;">Create</button>
    </div>
</form>
</div>

Note: Make sure your validation sub key is same as your asp-validation-for. You could check that on debug mode under results View as the below screenshot.

enter image description here

Controller:

public async Task<IActionResult> OnPost(Category category)
        {
            if (ModelState.IsValid)
            {
                await _db.Categories.AddAsync(category);
                await _db.SaveChangesAsync();
                return RedirectToPage("Index");
            }
            return View("Index");
        }

Output:

enter image description here

Debugging Steps:

enter image description here

How can I debug the model? Or look at how it is using the data annotations?

  1. Check the inspect element on your UI code.
  2. Make sure data-valmsg-for and name or id attributes are matched properly.
  3. See the below screen capture for details steps

enter image description here

Note:

Make sure you have _ValidationScriptsPartial.cshtml on your shared folder and it should contains following references:

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

enter image description here

enter image description here

You could refer to our official document for more details here.

日暮斜阳 2025-02-06 10:04:20

在codementor.io的帮助下,我们发现,当页面上存在错误并且您的服务器正在捕获错误时,您的模型状态会以无效的速度发送回客户端。如果您重定向到一个动作,则将破坏此缓存。在这种情况下,重定向到创建。cshtml在内存中清除了会话。只需重定向到页面,您就会看到服务器错误。

public async Task<IActionResult> OnPost()
        {
            if(Category.Name == Category.DisplayOrder.ToString())
            {
                ModelState.AddModelError("Category.Name", "Category name cannot be the same as category display order");
            }
            if (ModelState.IsValid)
            {
                await _db.Category.AddAsync(Category); //the BindProperties attribute above takes care of this--not having to pass category Category, just use a capital C to bind it to the Category model
                await _db.SaveChangesAsync();
                return RedirectToPage("Index");
            }
            else
                //2022-05-19, Problems were occurring on the error messages returned and displayed (i.e., they were not) from the server. 
                //
                //Resolved on codementor.io: When ModelState.Isvalid returns false,
                //you do not need to redirect to Create.cshtml, ***because the state of the model will be lost, because model state is stored
                //in memory cache, i.e. by session; rather you just return the page (ie return Page())

                return Page(); <--return page, don't redirect to Create, or the action
                
        }

With the help of codementor.io, we figured out that when there is an error on the page and your server is catching the error, your ModelState is sent back to the client as Invalid. If you redirect to an action, you are destroying this cache. IN this case, redirecting to Create.cshtml cleared the session in memory. Just redirect to the Page, then you will see the server errors.

public async Task<IActionResult> OnPost()
        {
            if(Category.Name == Category.DisplayOrder.ToString())
            {
                ModelState.AddModelError("Category.Name", "Category name cannot be the same as category display order");
            }
            if (ModelState.IsValid)
            {
                await _db.Category.AddAsync(Category); //the BindProperties attribute above takes care of this--not having to pass category Category, just use a capital C to bind it to the Category model
                await _db.SaveChangesAsync();
                return RedirectToPage("Index");
            }
            else
                //2022-05-19, Problems were occurring on the error messages returned and displayed (i.e., they were not) from the server. 
                //
                //Resolved on codementor.io: When ModelState.Isvalid returns false,
                //you do not need to redirect to Create.cshtml, ***because the state of the model will be lost, because model state is stored
                //in memory cache, i.e. by session; rather you just return the page (ie return Page())

                return Page(); <--return page, don't redirect to Create, or the action
                
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文