La coutume de la liaison de modèle, de modèle d'état, et les annotations de données
J'ai quelques questions au sujet de la coutume de la liaison de modèle, de modèle d'état, et les annotations de données.
1) Est-il redondant de faire la validation dans le modèle de liaison personnalisé si j'ai des données annotations sur mon modèle, parce que c'est ce que je pensais, le point de données annotations ont été.
2) Pourquoi mon contrôleur de traiter le modèle de l'état comme valide même quand il ne l'est pas, j'en ai principalement que le Nom de la propriété null ou trop court.
3) Est-il correct de penser à des classeurs de modèles personnalisés comme les méthodes constructeur, parce que c'est ce qu'ils me rappellent.
D'abord voici mon modèle.
public class Projects
{
[Key]
[Required]
public Guid ProjectGuid { get; set; }
[Required]
public string AccountName { get; set; }
[Required(ErrorMessage = "Project name required")]
[StringLength(128, ErrorMessage = "Project name cannot exceed 128 characters")]
[MinLength(3, ErrorMessage = "Project name must be at least 3 characters")]
public string Name { get; set; }
[Required]
public long TotalTime { get; set; }
}
Alors que je suis en utilisant un modèle de liaison personnalisé pour lier certaines propriétés du modèle. S'il vous plaît ne pas l'esprit que c'est rapide et sale juste essayer d'obtenir qu'elle fonctionne et ensuite le refactoring.
public class ProjectModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
var p = new Project();
p.ProjectGuid = System.Guid.NewGuid();
p.AccountName = controllerContext.HttpContext.User.Identity.Name;
p.Name = controllerContext.HttpContext.Request.Form.Get("Name");
p.TotalTime = 0;
//
//Is this redundant because of the data annotations?!?!
//
if (p.AccountName == null)
bindingContext.ModelState.AddModelError("Name", "Name is required");
if (p.AccountName.Length < 3)
bindingContext.ModelState.AddModelError("Name", "Minimum length is 3 characters");
if (p.AccountName.Length > 128)
bindingContext.ModelState.AddModelError("Name", "Maximum length is 128 characters");
return p;
}
}
Maintenant mon contrôleur de l'action.
[HttpPost]
public ActionResult CreateProject([ModelBinder(typeof(ProjectModelBinder))]Project project)
{
//
//For some reason the model state comes back as valid even when I force an error
//
if (!ModelState.IsValid)
return Content(Boolean.FalseString);
//_projectRepository.CreateProject(project);
return Content(Boolean.TrueString);
}
MODIFIER
J'ai Trouvé un code sur un autre stackoverflow question, mais je ne suis pas sûr à quel point je voudrais injecter les valeurs suivantes dans cette solution possible.
Ce que je veux injecter lorsqu'un nouvel objet est créé:
var p = new Project();
p.ProjectGuid = System.Guid.NewGuid();
p.AccountName = controllerContext.HttpContext.User.Identity.Name;
p.Name = controllerContext.HttpContext.Request.Form.Get("Name");
p.TotalTime = 0;
Comment puis-je obtenir le code ci-dessus dans ce qui est ci-dessous (solution):
public class ProjectModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(Project))
{
ModelBindingContext newBindingContext = new ModelBindingContext()
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
() => new Project(), //construct a Project object,
typeof(Project) //using the Project metadata
),
ModelState = bindingContext.ModelState,
ValueProvider = bindingContext.ValueProvider
};
//call the default model binder this new binding context
return base.BindModel(controllerContext, newBindingContext);
}
else
{
return base.BindModel(controllerContext, bindingContext);
}
}
}
}
OriginalL'auteur Odnxe | 2011-04-28
Vous devez vous connecter pour publier un commentaire.
Vous trouverez des choses de travail beaucoup plus facile si vous héritez de la
DefaultModelBinder
, remplacer laBindModel
méthode, appelez lebase.BindModel
méthode, puis faire les modifications manuelles (réglage de l'guid, le nom du compte et le temps total).1) Il est inutile de les valider comme vous l'avez fait. Vous pouvez écrire du code pour refléter la validation des métadonnées comme le défaut n', ou tout simplement supprimer les annotations de données de validation, puisque vous ne l'utilisez pas dans votre modèle de classeur.
2) je ne sais pas, il semble correct, vous devez parcourir le code, et assurez-vous que votre classeur personnalisé remplissage de toutes les règles applicables.
3) Il s'agit d'une usine pour sûr, mais pas tellement d'un constructeur.
EDIT: vous ne pouvez pas être plus près de la solution, il suffit de définir les propriétés dont vous avez besoin dans le modèle de l'usine de la fonction
Ou vous pouvez alternativement remplacer la
CreateModel
méthode:Ou peut-être vous avez un moyen plus simple de réaliser la même chose.
il est difficile d'obtenir beaucoup plus proche que vous ne l'étiez, j'ai mis en place ce dans MVC3 pour vérifier qu'il fonctionne comme prévu (ou au moins ma compréhension de votre intention).
Génial, Merci pour le dernier petit peu d'aide! Je savais que j'étais proche, je suis juste assez nouveau modèle de liaison et MVC en général. Vous m'avez sauvé des heures et des heures de maux de tête.
Les deux solutions fonctionnent, c'est juste une préférence chose pour aller avec l'un ou l'autre? Ou est une approche intrinsèquement meilleur que l'autre?
OriginalL'auteur Nick Larsen