ModelState est à venir comme invalide?
Je suis en train de travailler sur un MVC5 Code-Première application.
Sur un Modèle de Edit()
vue, j'ai compris [Create]
boutons pour ajouter de nouvelles valeurs à d'autres modèles dans le Edit()
la vue et de repeupler la nouvelle valeur dans DropDownFors()
sur le Edit()
.
Pour cette première tentative, je suis de passage d'un model_description
via AJAX à ma méthode de contrôleur createNewModel()
:
[HttpPost]
public JsonResult createNewModel(INV_Models model)
{
//model.model_description is passed in via AJAX -- Ex. 411
model.created_date = DateTime.Now;
model.created_by = System.Environment.UserName;
model.modified_date = DateTime.Now;
model.modified_by = System.Environment.UserName;
//Set ID
int lastModelId = db.INV_Models.Max(mdl => mdl.Id);
model.Id = lastModelId+1;
//if (ModelState.IsValid == false && model.Id > 0)
//{
// ModelState.Clear();
//}
//Attempt to RE-Validate [model], still comes back "Invalid"
TryValidateModel(model);
//Store all errors relating to the ModelState.
var allErrors = ModelState.Values.SelectMany(x => x.Errors);
//I set a watch on [allErrors] and by drilling down into
//[allErrors]=>[Results View]=>[0]=>[ErrorMessage] I get
//"The created_by filed is required", which I'm setting....?
try
{
if (ModelState.IsValid)
{
db.INV_Models.Add(model);
db.SaveChangesAsync();
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(
new { ID = model.Id, Text = model.model_description },
JsonRequestBehavior.AllowGet);
}
Ce que je ne peut pas comprendre est pourquoi mon ModelState
est à venir comme Invalid
?
Toutes les propriétés sont spécifiées avant le ModelState
vérifier; le Modèle est défini comme suit:
public class INV_Models
{
public int Id { get; set; }
[Required(ErrorMessage = "Please enter a Model Description.")]
public string model_description { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime created_date { get; set; }
[Required]
public string created_by { get; set; }
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime modified_date { get; set; }
public string modified_by { get; set; }
}
MODIFIER:
Ajouté Afficher le code:
Formulaire De Saisie:
<span class="control-label col-md-2">Type:</span>
<div class="col-md-4">
@Html.DropDownListFor(model => model.Type_Id, (SelectList)ViewBag.Model_List, "<<< CREATE NEW >>>", htmlAttributes: new { @class = "form-control dropdown" })
@Html.ValidationMessageFor(model => model.Type_Id, "", new { @class = "text-danger" })
</div>
<div class="col-md-1">
<div class="btn-group">
<button type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
SCRIPT:
$('#submitNewModel').click(function () {
var form = $(this).closest('form');
var data = { model_description: document.getElementById('textNewModel').value };
$.ajax({
type: "POST",
dataType: "JSON",
url: '@Url.Action("createNewModel", "INV_Assets")',
data: data,
success: function (resp) {
alert("SUCCESS!");
$('#selectModel').append($('<option></option>').val(resp.ID).text(resp.Text));
alert("ID: " + resp.ID + " //New Model: " + resp.Text); //RETURNING 'undefined'...?
form[0].reset();
$('#createModelFormContainer').hide();
},
error: function () {
alert("ERROR!");
}
});
});
- Fournir le code de vous voir avec les données que vous envoyez.
- Vous n'êtes pas publier un
created_date
oucreated_by
de sorte que votreModelState
est pas valide lorsque vous postez en arrière. - Pouvez-vous développer? Voulez-vous dire quand je suis à l'affichage de la Vue à partir de la manette?
Vous devez vous connecter pour publier un commentaire.
Vous ne devriez pas utiliser un hack comme
ModelState.Clear()
niTryValidateModel(model);
nécessaire. Votre problème provient du fait que vous avez un[Required]
attribut à la fois sur votrecreated_date
etcreated_by
propriétés, mais vous ne publiez pas de retour à une valeur, de sorte qu'ils sontnull
et la validation échoue. Si vous étiez à publier un modèle plus complexe, alors vous devez utiliser un modèle de vue qui n'ont même pas de propriétés pourcreated_date
etcreated_by
(ses une méthode de création, de sorte qu'ils ne devraient pas être ensemble jusqu'à ce que vous publiez en arrière).Dans votre cas, un modèle de vue n'est pas nécessaire puisque votre seul affichage d'une seule valeur ( pour
model-description
) qui permet de créer un nouveauINV_Models
modèle.Changer la 2ème ligne dans le script pour
Changer votre méthode post pour
Notes:
modified_date
êtreDateTime?
(prendre la valeur null dans la base de donnéeségalement). Vous êtes à la création d'un nouvel objet, et de la définition de la
created_date
etcreated_by
propriétés, mais la définition d'modified_date
etmodified_by
propriétés ne semble pasapproprié (il n'a pas été modifié encore).
created_by
àSystem.Environment.UserName
(il serait inutile d'avoirchaque ensemble d'enregistrements à
administrator
ou quoi queUserName
de l'serveur renvoie. Au lieu de cela vous avez besoin pour obtenir des noms d'utilisateurs, de
Identity
ou
Membership
quel que soit le système d'autorisation que vous utilisez.ModelState.Clear()
&TryValidate()
. Tous les 3 propriétés avec[Required]
ont une valeur. LeDescription
transmis au contrôleur via JSON, puiscreated_date
/created_by
étant donné une valeur dans le contrôleur (à droite avant l'enregistrement), mais sans compensation de l'état et de la revalidation, j'ai été encore une défaillance de l'erreur du modèle. Concernant les notes, j'ai mis en œuvre n ° 1 -- NeDateTime?
sur la classe principale, mais pas pour les autres pour une raison quelconque. #2 - Pas sûr de ce que la méthode va être encore utilisé. Juste une idée courante en attente d'examen.ModelState.Clear()
etc. peut être éviter si j'ai passé une valeur pourcreated_by
etcreated_date
avec monmodel_description
pour mondata
variable, mais lorsque je tentevar data = { model_description: document.getElementById('textNewModel').value, created_date: @DateTime.Now, created_by: @System.Environment.UserName };
le script ne s'exécute jamais au contrôleur, à défaut avec: "Nombre Inattendu" -var data = { model_description: document.getElementById('textNewModel').value, created_date: 2/17/2015 3:51:15 PM, created_by: JSmith };
...?INV_Models model
. La valeur par défautModelBinder
première initialise une nouvelle instance du modèle, puis définit ses propriétés basées sur les valeurs envoyées. Parce que vous ne publiez pas n'importe quoi pourcreated_by
sa valeur est la valeur par défaut (null
) mais ensuite, un modèle d'état d'erreur est ajoutée en raison de laRequired
attribut. Il suffit de faire le paramètrestring description
comme ci-dessus.created_date
de la vue. Un utilisateur pourrait avoir commencé à le faire hier, se distraire et de le finir aujourd'hui. Votre code devrait définir la date de création de la base de données comme hiers date (j'.e la mauvaise date!) parce que@DateTime.Now
est la date à laquelle la page a été chargée pour la première fois.ModelBinder
à la recherche d'une instance de mon modèle alors que mon paramètre est l'initialisation de l'autre.ModelBinding
ou pendantSave()
) leID
obtenir une valeur de définir les coulisses d'un nouveau Modèle d'enregistrement?ID
propriété est une auto-incrémenté clé dans la base de données, EF mise à jour de la valeur lorsque vous ajoutez un nouvel enregistrement lorsque vous appelezdb.SaveChangesAsync();
- mais pourquoi faites-vous ce que asynchrone?[X] create async methods
lors de la création de laController
.Lorsque vous ne pouvez pas rapidement en déduire pourquoi votre ModelState la validation échoue, il est souvent utile de rapidement effectuer une itération sur les erreurs.
Sinon, vous pouvez sortir directement les erreurs.
Gardez à l'esprit que la ModelState construit AVANT le corps de votre Action est exécutée. En conséquence, IsValid sera déjà ensemble, indépendamment de la façon dont vous définissez vos propriétés du modèle une fois que vous êtes à l'intérieur de l'Action du Contrôleur.
Si vous voulez la flexibilité de définir manuellement les propriétés et puis re-evalute la validité de l'objet, vous pouvez le relancer manuellement la validation à l'intérieur de votre Action après la mise à l'propriétés. Comme indiqué dans les commentaires, vous devez effacer vos ModelState avant de tenter de le revalider.
En aparté, si le modèle n'est toujours pas valide ValidateModel(modèle) lèvera une exception. Si vous voulez éviter cela, utilisez de l' TryValidateModel, qui renvoie la valeur true/false à la place:
ValidateModel()
etTryValidateModel()
, mais les deux sont de retour en tant queInvalid
. Ensuite, j'ai utilisé votre approche avecallErrors
et mettre une montre surallErrors
. Le forage vers le bas dans le[Results View]=>[0]=>[ErrorMessage]
- je obtenir"The created_by field is required."
j'ai confirmé que je SUIS en précisant lecreated_by
valeur...?model.created_by = System.Environment.UserName
n'est pasnull
. Je l'ai eu à travailler en faisant unModelState.Clear()
AVANT d'essayerTryValidateModel(model)
. Une fois que cela se produit, tout fonctionne comme prévu. J'ai aussi dû changerdb.SaveChanges()
vsdb.SaveChangesAsync()
sinon la valeur n'aurez ajouté DB si j'avais un point d'arrêt. Sans, le code de traiter rapidement et de rentrer avant la DB ajouter a eu lieu.Le modèle de l'état est calculée lors de la liaison à partir de votre poste de données de modèle est fait.
Le ModelState.La propriété IsValid ne vous raconte pas si il ya des erreurs dans ModelState.Erreurs.
Lorsque vous définissez votre date de création, vous devrez supprimer l'erreur liées à de ModelState.Les erreurs
ModelState
a été vérifié lors de la liaison d'appel (si cela fait sens). J'ai confirmé à l'aide de David est l'approche que leModelState
semble le penser il est invalide en raison de lacreated_by
champ est requis, mais je suis en précisant que la valeur??ModelState
. Voir la réponse à cette question stackoverflow.com/questions/2588588/...TryValidateModel()
etValidateModel()
serait effacer l'erreur et effectuer une nouvelle Validation? Qu'est-ce exactement aurais-je préciser àRemove
?ModelState.Errors
qui, je crois, serait"created_date"
ModelState.Clear()
avantTryValidateModel(model)
.db.SaveChangesAsync()
n'est pas totalement terminer avant le retour se fait?