创建时显示“ Id字段为必填”验证消息;ID未设置为[必填]


72

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

POCO具有以下属性:

public int Id {get;set;}

[Required]
public string Message {get; set}

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

ModelState说“ Id字段是必需的”,但我没有将其设置为。这里有自动的东西吗?

编辑-原因揭示

布拉德·威尔逊(Brad Wilson)通过保罗·斯佩兰萨(Paul Speranza)在他说的以下评论之一中回答了这个问题的原因(欢呼保罗):

您正在提供ID的值,只是不知道您的身份。它位于默认路由(“ {controller} / {action} / {id}”)的路由数据中,其默认值为空字符串,该字符串对int无效。使用操作参数上的[Bind]属性来排除ID。我的默认路由是:new {controller =“ Customer”,action =“ Edit”,id =“”} //参数默认值

编辑-更新模型技术

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

    [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);
    }

1
:您可能会发现这个博客帖子有趣bradwilson.typepad.com/blog/2010/01/...
罗伯特·哈维

我确实发现它很有趣。不能解决此问题,但是可以帮助我想到我将要
Dan 2010年

1
如何使“ Id”类型安全?像()=> id之类的东西?
helloworld,2012年

Answers:


89

您可以添加属性:

 [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-我有一本书中的内容(专业MVC 1.0不在我的脑海)。但您也可以在Google上搜索“ asp.net mvc绑定排除”,这里有一些示例用法。
Rosstified 2010年

如何进行前端验证?JAVASCRIPT正在寻求“必需的”值...
Cherven

1
那对我不起作用。我将其添加到操作中,但仍然出现错误。
Shimmy Weitzhandler,2015年

@Rosstified我曾经Ajax.BeginForm()发布过数据。使用单个按钮保存/更新时,如何处理两种不同的操作方法?
Balagurunathan Marimuthu

18

我遇到了一种形式,该形式是我将“对象”动态添加到列表中。因此,我们的用户能够添加,删除或更新。除了创建新项目的情况以外,其他所有方法都运行良好。因此,就我而言,排除Id属性不是选项解决方案是使ID为Nullable

public int? Id { get; set; }

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


就我而言,最好的解决方案。谢谢。
约翰

优秀的!!真的帮了我!
imdadhusen

11

很棒的问题和答案,救了我的...。不过,我需要添加一些内容:

代替

[Bind(Exclude = "Id")]

我认为最好用

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

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

由于这是白名单,而不是黑名单。白名单更好,更安全。这样,您还可以解决过度发布和发布不足的风险。参见布拉德·威尔逊(Brad Wilson)的帖子


同意 如果您不使用视图模型,则可以轻松获取haX0rd。

是的 例如,我在“帐户”控制器上有一个CreateUser操作。User模型的属性之一是UserType,它是一个包含User,...,Admin的枚举。如果他要发布一个名为UserType的隐藏字段,并且其值为“ Admin”,并且我不会使用这种形式的Bind属性,那么我的网站上将有WAY Admins Admins =))
AndreiRînea10年

不错的转弯。但是,在大型应用程序中,这将是一项繁琐的任务。您可能最终会丢失一些道具,并且将来如果您决定添加一个不在列表中的道具,将其添加到视图中还不够,这将需要重新发布整个应用程序才能重新编译。
有用蜜蜂

7
[Bind(Exclude = "Id")]
public class Hebe
{
      public int Id {get;set;}

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

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


在更新时,您需要记录并使用UpdateModel来更新记录。因此,您具有数据库记录中的ID
Barbaros Alp,2010年

@BarbarosAlp我曾经Ajax.BeginForm()发布过数据。使用单个按钮保存/更新时,如何处理两种不同的操作方法?
Balagurunathan Marimuthu

7

Id应该从客户端发送为0。Id= 0时模型没有问题,这是int的默认值。问题在于他看不到来自客户端的值,或者它带有空格或null。我隐藏了一个代表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"/>

另外,当我在客户端将表单重置为“添加新实体”时,请确保使用零初始化隐藏对象。

希望这对您有所帮助。

f


2

我也有同样的问题,将RC2与POCO一起使用。如果您命名属性ID,但不在其上放置验证属性,但IsValid则表示它是必需的。如果我给某个属性命名,但没有ID,则不会发生。为什么我必须排除ID?

谢谢


3
我刚刚从布拉德·威尔逊(Brad Wilson)那里得到了这个分析器:您正在提供ID值,您只是不知道自己是谁。它位于默认路由(“ {controller} / {action} / {id}”)的路由数据中,其默认值为空字符串,该字符串对int无效。使用操作参数上的[Bind]属性来排除ID。我的默认路由是:new {controller =“ Customer”,action =“ Edit”,id =“”} //参数默认值
Paul Speranza 2010年

啊!在跟我开玩笑...是有道理的,但我永远都不会发现这一点
Dan 2010年


2

签入您的视图。如果您具有id的hiddenfieldfor字段,则将其删除。仅用于编辑。@ Html.HiddenFor(Model => Model.Id)


1

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

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。但是,默认模型联编程序不应显示您描述的行为。


1

在我的情况下,问题出在ID是type的事实string。更改为int(不可为空)对我来说已修复。该string类型是对设计不良的数据库进行反向工程的结果。


0

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


0

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


0

我遇到了同样的问题,并设法通过在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)

这样,我不必显式指定Bind属性


0

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

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

希望对您有用。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.