Lorsque j'utilise UpdateModel ou TryUpdateModel, le framework MVC est suffisamment intelligent pour savoir si vous essayez de passer un null à un type de valeur (par exemple, l'utilisateur oublie de renseigner le champ requis du jour de naissance).
Malheureusement, je ne sais pas comment remplacer le message par défaut, "Une valeur est requise". dans le résumé en quelque chose de plus significatif ("S'il vous plaît entrez dans votre jour de naissance").
Il doit y avoir un moyen de le faire (sans écrire trop de code de contournement), mais je ne le trouve pas. De l'aide?
MODIFIER
De plus, je suppose que cela poserait également un problème pour les conversions non valides, par exemple. BirthDay = "Bonjour".
Créez votre propre ModelBinder en étendant DefaultModelBinder:
public class LocalizationModelBinder : DefaultModelBinder
Remplacer SetProperty:
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
foreach (var error in bindingContext.ModelState[propertyDescriptor.Name].Errors.
Where(e => IsFormatException(e.Exception)))
{
if (propertyDescriptor.Attributes[typeof(TypeErrorMessageAttribute)] != null)
{
string errorMessage =
((TypeErrorMessageAttribute)propertyDescriptor.Attributes[typeof(TypeErrorMessageAttribute)]).GetErrorMessage();
bindingContext.ModelState[propertyDescriptor.Name].Errors.Remove(error);
bindingContext.ModelState[propertyDescriptor.Name].Errors.Add(errorMessage);
break;
}
}
Ajoutez la fonction bool IsFormatException(Exception e)
pour vérifier si une exception est une exception FormatException:
if (e == null)
return false;
else if (e is FormatException)
return true;
else
return IsFormatException(e.InnerException);
Créez une classe d'attribut:
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
public class TypeErrorMessageAttribute : Attribute
{
public string ErrorMessage { get; set; }
public string ErrorMessageResourceName { get; set; }
public Type ErrorMessageResourceType { get; set; }
public TypeErrorMessageAttribute()
{
}
public string GetErrorMessage()
{
PropertyInfo prop = ErrorMessageResourceType.GetProperty(ErrorMessageResourceName);
return prop.GetValue(null, null).ToString();
}
}
Ajoutez l'attribut à la propriété que vous souhaitez valider:
[TypeErrorMessage(ErrorMessageResourceName = "IsGoodType", ErrorMessageResourceType = typeof(AddLang))]
public bool IsGood { get; set; }
AddLang est un fichier resx et IsGoodType est le nom de la ressource.
Et ajoutez enfin ceci dans Global.asax.cs Application_Start:
ModelBinders.Binders.DefaultBinder = new LocalizationModelBinder();
À votre santé!
Avec DefaultModelBinder, il est possible de remplacer le message d'erreur requis par défaut, mais malheureusement, il s'appliquerait globalement, quel IMHO le rend complètement inutile. Mais si vous décidez de le faire, voici comment:
PropertyValueRequired
et une valeurDans Application_Start, ajoutez la ligne suivante:
DefaultModelBinder.ResourceClassKey = "Messages";
Comme vous pouvez le constater, il n'y a pas de lien entre la propriété de modèle que vous validez et le message d'erreur.
En conclusion, il est préférable d'écrire une logique de validation personnalisée pour gérer ce scénario. Une solution consisterait à utiliser un type nullable (System.Nullable <TValueType>) puis:
if (model.MyProperty == null ||
/** Haven't tested if this condition is necessary **/
!model.MyProperty.HasValue)
{
ModelState.AddModelError("MyProperty", "MyProperty is required");
}
J'utilise le cadre génial xVal validation. Cela me permet de faire toute ma validation dans le modèle (même LINQ-SQL :)). Il émet également le javascript requis pour la validation côté client.
EDIT: Désolé, le lien n'a pas été lu pour savoir comment le faire fonctionner pour LINQ-SQL
Le flux de travail de base va quelque chose comme ça.
public partial class YourClass
{
[Required(ErrorMessage = "Property is required.")]
[StringLength(200)]
public string SomeProperty{ get; set; }
}
try
{
// Validate the instance of your object
var obj = new YourClass() { SomeProperty = "" }
var errors = DataAnnotationsValidationRunner.GetErrors(obj);
// Do some more stuff e.g. Insert into database
}
catch (RulesException ex)
{
// e.g. control name 'Prefix.Title'
ex.AddModelStateErrors(ModelState, "Prefix");
ModelState.SetModelValue("Prefix.Title", new ValueProviderResult(ValueProvider["Prefix.Title"].AttemptedValue, collection["Prefix.Title"], System.Globalization.CultureInfo.CurrentCulture));
}
que dis-tu de ça?
[RegularExpression(@"^[a-zA-Z''-'\s]{1,40}$",
ErrorMessage = "Characters are not allowed.")]
Cela devrait vous permettre de baliser les propriétés avec des messages d'erreur spécifiques pour les validateurs MVC que vous souhaitez utiliser ...
Dans ASP.NET MVC 1, j'ai également rencontré ce problème.
Dans mon projet, il existe un modèle ou un objet métier nommé "Entrée", et sa clé primaire EntryId est int? type, et la valeur de EntryId peut être autorisée par les utilisateurs.
Le problème est donc, lorsque le champ est vide ou zéro ou une valeur entière qui a existé, les messages d'erreur personnalisés peuvent être affichés bien, mais si la valeur est une valeur non-entière comme "un", je ne peux pas trouver un moyen utiliser le message personnalisé pour remplacer le message par défaut tel que "La valeur 'a' n'est pas valide".
lorsque je suis le message d'erreur dans ModelState, j'ai trouvé que la valeur n'est pas un entier, il y aura deux erreurs liées à EntryId et le message d'erreur du premier élément est vide ...
Maintenant, je dois utiliser un code si laid pour pirater le problème.
if (ModelState["EntryId"].Errors.Count > 1)
{
ModelState["EntryId"].Errors.Clear(); //should not use ModelState["EntryId"].remove();
ModelState.AddModelError("EntryId", "必须为大于0的整数"); //必须为大于0的整数 means "it should be an integer value and great than 0"
}
mais cela rend le contrôleur gros, espérons qu'il existe une vraie solution pour le résoudre.
Recherchez ModelState.AddError
.
oui, vous pouvez utiliser System.ComponentModel.DataAnnotationsen combinaison avec xValet vous pourrez définir des règles de validation et des messages (vous pouvez même utiliser des fichiers de ressources pour la localisation) pour chacune de vos propriétés à l'aide d'attributs
regardez icihttp://blog.codeville.net/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/