【问题标题】:"The Id field is required" validation message on Create; Id not set to [Required]创建时的“Id 字段是必需的”验证消息; Id 未设置为 [必需]
【发布时间】:2010-01-26 22:01:55
【问题描述】:

当我尝试在 Asp.Net MVC 2 中使用创建样式操作创建实体时,就会发生这种情况。

POCO 具有以下属性:

public int Id {get;set;}

[Required]
public string Message {get; set}

在创建实体时,会自动设置 Id,因此在 Create 操作中不需要它。

ModelState 说“需要 Id 字段”,但我没有这样设置。 这里有自动发生的事情吗?

编辑 - 原因揭晓

Brad Wilson 通过 Paul Speranza 在下面的其中一个 cmets 中回答了问题的原因,他说(为 Paul 喝彩):

您正在为 ID,你只是不知道你是。 它在默认的路由数据中 路线(“{controller}/{action}/{id}”), 其默认值为空 字符串,对 int 无效。 使用您的 [Bind] 属性 用于排除 ID 的操作参数。我的 默认路由是:新 { 控制器 = "客户", action = "编辑", id = " " } // 参数默认值

编辑 - 更新模型技术

实际上,我通过使用 TryUpdateModel 和与之相关的排除参数数组再次改变了执行此操作的方式。

    [HttpPost]
    public ActionResult Add(Venue collection)
    {
        Venue venue = new Venue();
        if (TryUpdateModel(venue, null, null, new[] { "Id" }))
        {
            _service.Add(venue);
            return RedirectToAction("Index", "Manage");
        }
        return View(collection);
    }

【问题讨论】:

  • 您可能会觉得这篇博文很有趣:bradwilson.typepad.com/blog/2010/01/…
  • 我确实觉得它很有趣。不能解决这个问题,但可以帮助我想到我将要拥有的其他一些问题
  • 如何使“Id”类型安全?像 ()=>id ?

标签: asp.net-mvc asp.net-mvc-2 data-annotations


【解决方案1】:

可以添加属性:

 [Bind(Exclude = "Id")] 

在方法中的参数而不是类上,这样在创建时您可以将其排除在外,在编辑时它仍然是强制性的:

public ActionResult Create([Bind(Exclude = "Id")] User u)
{
    // will exclude for create
}

public ActionResult Edit(User u)
{
    // will require for edit
}

【讨论】:

  • 不错。我认为这会奏效。我曾在某个地方看到过,但再也找不到了。你在哪里找到的?
  • @burnt_hand - 它在我的一本书中(Professional MVC 1.0 off my head)。但你也可以谷歌“asp.net mvc bind exclude”,有一些示例用法。
  • 如何处理前端验证? JAVASCRIPT 要求“必需”值...
  • 这对我不起作用。我将其添加到操作中,但我仍然收到错误。
  • @Rosstified 我使用Ajax.BeginForm() 发布数据。使用单个按钮保存/更新时如何处理两种不同的操作方法?
【解决方案2】:

我遇到了这个问题,我在其中动态地将“对象”添加到列表中。因此,我们的用户能够添加、删除或更新。除了创建新项目的情况外,一切都运行良好。出于这个原因,就我而言,排除 Id 属性不是一种选择解决方案是让 ID 为 Nullable

public int? Id { get; set; }

这样,现有项目将具有值,而新项目将具有 null。好东西。

【讨论】:

  • 对我来说最好的解决方案。谢谢。
  • 太棒了!!真的帮了我!
【解决方案3】:

很好的问题和答案,拯救了我的……落后。不过,我需要补充一点:

代替

[Bind(Exclude = "Id")]

我觉得比较好用

[Bind(Include = "Prop1, Prop2, Prop3, etc")]

.. 其中 Prop1、Prop2 和 Prop3 是您希望在操作级别绑定的唯一属性。

因为这是白名单而不是黑名单。白名单更好,更安全。这样,您还可以解决过度发布和发布不足的风险。见Brad Wilson's post

【讨论】:

  • 同意。如果您不使用视图模型,您可以轻松获得 haX0rd。
  • 是的。例如,我的帐户控制器上有一个 CreateUser 操作。 User 模型的属性之一是 UserType,它是一个包含 User、...、Admin 的枚举。如果他要发布一个名为 UserType 的隐藏字段并且它的值是“Admin”,而我不会使用这种形式的 Bind 属性,我的网站上会有太多管理员 =))
  • 不错的转折。但是,在大型应用程序中,这将是一项乏味的任务。您最终可能会丢失道具,并且将来如果您决定添加一个不在列表中的道具,将其添加到视图中是不够的,这将需要重新发布您的整个应用程序才能重新编译。跨度>
【解决方案4】:
[Bind(Exclude = "Id")]
public class Hebe
{
      public int Id {get;set;}

      [Required]
      public string Message {get; set}
}

通过上面的方式,它不会在创建时为您的模型绑定 Id 属性

【讨论】:

  • 更新时,需要取记录,使用UpdateModel更新记录。所以你有 db 记录中的 id
  • @BarbarosAlp 我使用Ajax.BeginForm() 发布数据。使用单个按钮保存/更新时如何处理两种不同的操作方法?
【解决方案5】:

ID 应该从客户端发送为 0。 模型Id=0没有问题,这是int的默认值。 问题是他没有看到来自客户端的值,或者它带有空格或空值。 我有一个隐藏的输入,它代表 Id(或在复杂对象 NestedPropertyId/NestedProperty.Id 中),所以我确保它以零值开头。

<input type="hidden" id="id" value="0" />
<input type="hidden" id="eventId" value="0"/>
<input type="hidden" id="contactId" value="0"/>

另外,当我在客户端重新设置表单以添加新实体时,我确保将隐藏的初始化为零。

希望这对某人有所帮助。

Efy

【讨论】:

    【解决方案6】:

    我有同样的问题,使用带有 POCO 的 RC2。如果您命名一个属性 Id 但没有在其上放置验证属性但 IsValid 说它是必需的。如果我将一个属性命名为除 ID 之外的任何名称,则不会发生这种情况。为什么我必须排除 Id?

    谢谢

    【讨论】:

    • 我刚刚从 Brad Wilson 那里得到了这个分析器:你为 ID 提供了一个值,你只是不知道你是。它在默认路由(“{controller}/{action}/{id}”)的路由数据中,其默认值为空字符串,对int无效。使用操作参数上的 [Bind] 属性来排除 ID。我的默认路由是:new { controller = "Customer", action = "Edit", id = " " } // 参数默认值
    • 啊!开玩笑...有道理,但我永远不会发现
    【解决方案7】:

    添加?到 int

    [Key]
    [HiddenInput(DisplayValue = false)]
    public int? ID { get; set; }
    

    【讨论】:

      【解决方案8】:

      查看您的视图。如果您有 id 字段的隐藏字段,请删除。这仅用于编辑。 @Html.HiddenFor(Model => Model.Id)

      【讨论】:

        【解决方案9】:

        我刚刚创建了一个新的 MVC2 项目,并添加了一个简单的 POCO 以及一个控制器和一个视图。据我了解,您正在使用模型绑定来创建对象,即

        using System.ComponentModel.DataAnnotations;
        public class SimpleObject
        {
            public int Id {get;set;}
            [Required]
            public string Message { get; set; }
        }
        

        在我们拥有的控制器中

        [HttpPost]
        public ActionResult Create(SimpleObject created)
        {
            /// do something
        }
        

        在视图中,没有 ID 字段的编辑器?

        这不应以任何错误消息告终。相反,Id 应该设置为 default(int),即 0。这对我有用。您使用的是哪个版本的 MVC2(我假设是 RC)?

        不要误会我的意思:防止 Id 被模型绑定器绑定很重要,因为这将允许攻击者篡改对象的 Id。尽管如此,默认模型绑定器不应显示您描述的行为。

        【讨论】:

          【解决方案10】:

          在我的例子中,问题出在 ID 是 string 类型这一事实。更改为int(不可为空)为我修复了它。 string 类型是对设计不良的数据库进行逆向工程的结果。

          【讨论】:

            【解决方案11】:

            我有同样的问题,除了我的模型上有三个整数字段。我设法通过将所有错误地需要的整数属性设置为可空整数来解决它。

            【讨论】:

              【解决方案12】:

              以上答案都是正确的。无论如何,每个人都遵循不同的场景。对于相同的问题,我的解决方案如下。 如果您的 ID 是主键,那么您需要启动它我的意思是说,当您在 get 方法中传递模型以查看时,只需在它之前创建新对象。它会将您的 ID 设置为 0 而不是 null。

              【讨论】:

                【解决方案13】:

                我遇到了同样的问题,并通过在我的 Create 方法的 GET 调用期间简单地将视图模型的一个空实例传递给视图来解决它。

                //GET: DocumentTypes/{Controller}/Create
                    public ActionResult Create()
                    {
                        return View(new DocumentTypeViewModel());
                    }
                
                    //POST: DocumentTypes/{Controller}/Create
                    [HttpPost]
                    [ValidateAntiForgeryToken]
                    public ActionResult Create(DocumentTypeViewModel viewModel)
                    {
                        if(ModelState.IsValid) {
                
                            var result = AddDocumentType(viewModel);
                            if(!result.HasValidationErrors) {
                                return RedirectToAction("Index");
                            }
                
                            ModelState.Update(result);
                
                        }
                
                        return View(viewModel);
                    }
                

                然后在我看来,我确保我有

                @Html.HiddenFor(m => m.ID)
                

                这样我就不用显式指定绑定属性了

                【讨论】:

                  【解决方案14】:

                  我也遇到了同样的问题,现在我已经解决了。 使用 HttpGet 您需要返回一个 View 将是空模型。比如

                  [HttpGet]
                  public ActionResult Add()
                  {
                      //Your code here
                      return View(new Venue);
                  }
                  

                  希望对你有用。

                  【讨论】:

                    【解决方案15】:

                    您可以通过在DataAnnotationsModelValidatorProvider 上设置AddImplicitRequiredAttributeForValueTypes 选项来禁用此隐式验证,方法是将以下内容添加到您的Application_Start

                    DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
                    

                    进一步阅读

                    【讨论】:

                      【解决方案16】:

                      在检查 ModelState.IsValid 之前从 ModelState 中删除“Id”。

                      ModelState.Remove("Id");
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-06-01
                        • 1970-01-01
                        • 2017-06-06
                        • 2014-10-15
                        • 2019-10-19
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多