Validierungsnachricht "Das ID-Feld ist erforderlich" beim Erstellen; ID nicht auf [Erforderlich] gesetzt

72

Dies geschieht, wenn ich versuche, die Entität mithilfe einer Aktion zum Erstellen eines Stils in Asp.Net MVC 2 zu erstellen.

Der POCO hat folgende Eigenschaften:

public int Id {get;set;}

[Required]
public string Message {get; set}

Beim Erstellen der Entität wird die ID automatisch festgelegt, sodass sie für die Aktion "Erstellen" nicht erforderlich ist.

Der ModelState sagt, dass "Das ID-Feld erforderlich ist", aber ich habe das nicht so eingestellt. Ist hier etwas Automatisches los?

EDIT - Grund enthüllt

Der Grund für das Problem wird von Brad Wilson über Paul Speranza in einem der folgenden Kommentare beantwortet, in denen er sagt (Prost Paul):

Sie geben einen Wert für ID an, Sie wussten nur nicht, dass Sie es sind. Es befindet sich in den Routendaten der Standardroute ("{controller} / {action} / {id}") und der Standardwert ist die leere Zeichenfolge, die für ein int nicht gültig ist. Verwenden Sie das Attribut [Bind] für Ihren Aktionsparameter, um die ID auszuschließen. Meine Standardroute war: new {controller = "Customer", action = "Edit", id = ""} // Standardwerte für Parameter

BEARBEITEN - Modelltechnik aktualisieren

Ich habe die Art und Weise, wie ich dies erneut tat, tatsächlich geändert, indem ich TryUpdateModel und das damit verbundene Array mit den Ausschlussparametern verwendet habe.

    [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);
    }
Dan
quelle
1
Sie könnten diesen Blog-Beitrag interessant finden: bradwilson.typepad.com/blog/2010/01/…
Robert Harvey
Ich fand es interessant. Löst dieses Problem nicht, hilft mir aber, an einige andere zu denken, die ich haben würde
Dan
1
Wie kann ich den Typ "Id" sicher machen? So etwas wie () => id?
Helloworld

Antworten:

89

Sie können das Attribut hinzufügen:

 [Bind(Exclude = "Id")] 

Wenn Sie den Parameter in method anstelle der Klasse verwenden, können Sie ihn beim Erstellen ausschließen, und beim Bearbeiten ist er weiterhin obligatorisch:

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

public ActionResult Edit(User u)
{
    // will require for edit
}
Rosstified
quelle
Nett. Ich denke, das wird den Trick machen. Ich hatte es irgendwo gesehen, konnte es aber nicht wiederfinden. Wo hast du es gefunden?
Dan
@burnt_hand - Es ist in einem Buch, das ich habe (Professional MVC 1.0 auf den ersten Blick). Sie können aber auch "asp.net mvc bind exclude" googeln und es gibt einige Verwendungsbeispiele.
Rosstified
WIE BEHANDELE ICH MIT DER VORDEREN VORDERUNG? JAVASCRIPT BITTE UM 'ERFORDERLICHE' WERTE ...
Cherven
1
Das funktioniert bei mir nicht. Ich habe das zur Aktion hinzugefügt und erhalte immer noch den Fehler.
Shimmy Weitzhandler
@Rosstified Ich habe Ajax.BeginForm()Daten gepostet . Wie gehe ich beim Speichern / Aktualisieren mit einer einzigen Schaltfläche mit zwei verschiedenen Aktionsmethoden um?
Balagurunathan Marimuthu
18

Ich bin auf dieses Problem mit einem Formular gestoßen, in dem ich einer Liste dynamisch "Objekte" hinzugefügt habe. Daher konnten unsere Benutzer hinzufügen, entfernen oder aktualisieren. Es hat alles gut funktioniert, bis auf die Fälle, in denen neue Elemente erstellt wurden. Aus diesem Grund war in meinem Fall das Ausschließen der Id-Eigenschaft keine Option . Die Lösung bestand darin, die ID auf Null zu setzen :

public int? Id { get; set; }

Auf diese Weise haben vorhandene Elemente einen Wert und neue Elemente haben stattdessen null. Gutes Zeug.

Ulises
quelle
Beste Lösung in meinem Fall. Vielen Dank.
John
Ausgezeichnet!! hat mir wirklich geholfen!
Imdadhusen
11

Tolle Fragen und Antworten, rettete meinen ... Hintern. Ich muss jedoch etwas hinzufügen:

Anstatt

[Bind(Exclude = "Id")]

Ich denke, es ist besser zu verwenden

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

.. wobei Prop1, Prop2 und Prop3 DIE EINZIGEN Eigenschaften sind, die Sie auf Aktionsebene binden möchten.

Da dies eine weiße Auflistung im Gegensatz zu einer schwarzen Auflistung ist. White-Listing ist besser und sicherer. Auf diese Weise lösen Sie auch das Risiko von Über- und Unterbuchungen. Siehe Brad Wilsons Beitrag .

Andrei Rînea
quelle
Einverstanden. Sie können haX0rd leicht erhalten, wenn Sie keine Ansichtsmodelle verwenden.
Dan
Ja. Zum Beispiel habe ich eine CreateUser-Aktion auf meinem Account Controller. Eine der Eigenschaften des Benutzermodells ist UserType, eine Aufzählung, die User, ..., Admin enthält. Wenn er ein verstecktes Feld namens UserType mit dem Wert "Admin" veröffentlichen würde und ich diese Form des Bindungsattributs nicht verwenden würde, hätte ich auf meiner Website viel zu viele Administratoren =))
Andrei Rînea
Schöne Wendung. In großen Anwendungen wäre dies jedoch eine mühsame Aufgabe. Möglicherweise fehlen Requisiten. Wenn Sie in Zukunft eine hinzufügen, die nicht in der Liste enthalten ist, reicht es nicht aus, sie der Ansicht hinzuzufügen, und dies erfordert die erneute Veröffentlichung Ihrer gesamten Anwendung, um sie neu zu kompilieren.
nützlichBee
7
[Bind(Exclude = "Id")]
public class Hebe
{
      public int Id {get;set;}

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

Übrigens bindet es die ID-Eigenschaft für Ihr Modell beim Erstellen nicht

Barbaros Alp
quelle
Bei Updates müssen Sie den Datensatz nehmen und das UpdateModel verwenden, um den Datensatz zu aktualisieren. Sie haben also die ID aus der Datenbank
Barbaros Alp
@BarbarosAlp Ich habe Ajax.BeginForm()Daten gepostet . Wie gehe ich beim Speichern / Aktualisieren mit einer einzigen Schaltfläche mit zwei verschiedenen Aktionsmethoden um?
Balagurunathan Marimuthu
7

Die ID sollte vom Client als 0 gesendet werden. Das Modell hat kein Problem mit Id = 0, dies ist die Standardeinstellung von int. Das Problem ist, dass er den vom Client kommenden Wert nicht sieht oder er mit Leerzeichen oder Null kommt. Ich habe eine Eingabe ausgeblendet, die die ID darstellt (oder in einem komplexen Objekt NestedPropertyId / NestedProperty.Id), daher stelle ich sicher, dass sie mit dem Wert Null beginnt.

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

Auch wenn das Formular so eingestellt wird, dass auf der Clientseite eine neue Entität hinzugefügt wird, muss das versteckte Objekt mit Null initialisiert werden.

Hoffe das hilft jemandem.

Efy

user1911353
quelle
2

Ich habe das gleiche Problem mit RC2 mit einem POCO. Wenn Sie eine Eigenschafts-ID benennen, aber keine Validierungsattribute darauf setzen, IsValid jedoch angibt, dass dies erforderlich ist. Wenn ich einer Eigenschaft etwas anderes als ID nenne, geschieht dies nicht. Warum sollte ich die ID ausschließen müssen?

Vielen Dank

Paul Speranza
quelle
3
Und ich habe gerade diese Antwort von Brad Wilson erhalten: Sie geben einen Wert für den Ausweis an, Sie wussten einfach nicht, dass Sie es sind. Es befindet sich in den Routendaten der Standardroute ("{controller} / {action} / {id}") und der Standardwert ist die leere Zeichenfolge, die für ein int nicht gültig ist. Verwenden Sie das Attribut [Bind] für Ihren Aktionsparameter, um die ID auszuschließen. Meine Standardroute war: new {controller = "Customer", action = "Edit", id = ""} // Standardwerte für Parameter
Paul Speranza
Argh! Scherz mich ... macht Sinn, aber ich hätte das nie gefunden
Dan
2

hinzufügen ? zu int

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

Überprüfen Sie Ihre Ansicht. Entfernen Sie, wenn Sie ein Feld für ID versteckt haben. Dies wird nur zum Bearbeiten verwendet. @ Html.HiddenFor (Model => Model.Id)

Als Aramburo
quelle
1

Ich habe gerade ein neues MVC2-Projekt erstellt und einen einfachen POCO sowie einen Controller und eine Ansicht hinzugefügt. Soweit ich weiß, verwenden Sie die Modellbindung, um das Objekt zu erstellen

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

im Controller haben wir

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

und in der Ansicht gibt es keinen Editor für das ID-Feld?

Dies sollte nicht zu Fehlermeldungen führen. Stattdessen sollte die ID auf den Standardwert (int) gesetzt werden, der 0 ist. Dies funktioniert bei mir. Welche Version von MVC2 verwenden Sie (die RC nehme ich an)?

Verstehen Sie mich nicht falsch: Es ist wichtig zu verhindern, dass die ID an die Modellbinder gebunden wird, da ein Angreifer dadurch die ID des Objekts manipulieren kann. Der Standardmodellordner sollte jedoch nicht das von Ihnen beschriebene Verhalten anzeigen.

Mnemosyn
quelle
1

In meinem Fall war das Problem darauf zurückzuführen, dass es sich um eine ID handelte string. Der Wechsel zu einem int(nicht nullbaren) Fehler wurde für mich behoben. Der stringTyp war das Ergebnis des Reverse Engineering einer schlecht gestalteten Datenbank.

PBG
quelle
0

Ich hatte das gleiche Problem, außer dass ich drei ganzzahlige Felder in meinem Modell hatte. Ich habe es geschafft, es zu umgehen, indem ich alle meine ganzzahligen Eigenschaften, die fälschlicherweise benötigt wurden, auf nullbare Ints gesetzt habe.

kmehta
quelle
0

Die obigen Antworten sind richtig. Wie jeder einem anderen Szenario folgt. Meine Lösung lautet für dasselbe Problem wie folgt. Wenn Ihre ID ein Primärschlüssel ist, müssen Sie ihn initiieren. Ich meine, wenn Sie das Modell übergeben, um es in der get-Methode anzuzeigen, erstellen Sie einfach ein neues Objekt davor. Es wird 0 auf Ihre ID anstatt auf Null gesetzt.

Geeti
quelle
0

Ich hatte das gleiche Problem und konnte es lösen, indem ich während des GET-Aufrufs meiner Create-Methode einfach eine leere Instanz des Ansichtsmodells an die Ansicht übergab.

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

Und dann stelle ich aus meiner Sicht sicher, dass ich habe

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

Auf diese Weise muss ich keine Bindungsattribute explizit angeben

jspaey
quelle
0

Ich hatte auch das gleiche Problem mit Ihnen und jetzt habe ich dieses Problem bereits gelöst. Mit HttpGet müssen Sie ein Modell zurückgeben, das leer ist. Sowie

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

Ich hoffe es ist nützlich für dich.

user3717418
quelle
0

Sie können diese implizite Validierung deaktivieren, indem Sie die AddImplicitRequiredAttributeForValueTypesOption auf setzen, DataAnnotationsModelValidatorProviderindem Sie Folgendes zu Ihrem hinzufügen Application_Start:

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

Weiterführende Literatur :

KyleMit
quelle
0

Bevor Sie ModelState.IsValid überprüfen, entfernen Sie 'Id' aus ModelState.

ModelState.Remove("Id");
MohammadSoori
quelle