187 votes

ASP.NET MVC : Meilleure façon de couper les cordes après la saisie de données. Je devrais créer un classeur de modèles personnalisés ?

Je suis à l'aide d'ASP.NET MVC et j'aimerais que tout utilisateur a entré les champs de type chaîne à découper avant de l'insertion dans la base de données. Et depuis j'ai beaucoup de formes d'entrée de données, je suis à la recherche d'une élégante façon de couper toutes les cordes au lieu d'explicitement le parage chaque utilisateur a fourni de la chaîne de valeur. Je suis intéressé de savoir comment et quand les gens sont en train de tailler des chaînes de caractères.

J'ai pensé à peut-être la création d'un modèle personnalisé de liant et de découpage de la chaîne des valeurs...de cette façon, tous mes parage logique est contenue dans un seul endroit. Est-ce une bonne approche? Existe-il des exemples de code pour faire cela?

224voto

takepara Points 5965
<pre><code></code><p>Que diriez-vous de ce code ?</p><pre><code></code></pre><p>Définissez l’événement Application_Start global.asax.</p></pre>

79voto

Korayem Points 2665

Il s’agit de @takepara même résolution mais comme un IModelBinder au lieu de DefaultModelBinder ainsi que l’ajout de la modelbinder dans global.asax est par le biais

La classe :

basé sur le post de @haacked : http://haacked.com/archive/2011/03/19/fixing-binding-to-decimals.aspx

47voto

Anton Points 211

Une amélioration à la réponse @takepara.

Somewere projet :

Changement de classe de TrimModelBinder

À

et vous pouvez marquer des propriétés à être exclues de la tonte avec l’attribut [NoTrim].

13voto

Code Chief Points 422

Une autre variante de @takepara de réponse, mais avec une tournure différente:

1) je préfère l'opt-in "StringTrim" attribut mécanisme (plutôt que de l'opt-out "NoTrim" exemple de @Anton).

2) Un appel supplémentaire à SetModelValue est nécessaire pour assurer la ModelState est rempli correctement et la validation par défaut/accepter/rejeter le modèle peut être utilisé comme d'habitude, c'est à dire tryupdatemodel pour mettre(modèle) pour appliquer et ModelState.Clear() pour accepter toutes les modifications.

Mettez ceci dans votre entité/bibliothèque partagée:

/// <summary>
/// Denotes a data field that should be trimmed during binding, removing any spaces.
/// </summary>
/// <remarks>
/// <para>
/// Support for trimming is implmented in the model binder, as currently
/// Data Annotations provides no mechanism to coerce the value.
/// </para>
/// <para>
/// This attribute does not imply that empty strings should be converted to null.
/// When that is required you must additionally use the <see cref="System.ComponentModel.DataAnnotations.DisplayFormatAttribute.ConvertEmptyStringToNull"/>
/// option to control what happens to empty strings.
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class StringTrimAttribute : Attribute
{
}

Ensuite dans votre application MVC/bibliothèque:

/// <summary>
/// MVC model binder which trims string values decorated with the <see cref="StringTrimAttribute"/>.
/// </summary>
public class StringTrimModelBinder : IModelBinder
{
    /// <summary>
    /// Binds the model, applying trimming when required.
    /// </summary>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Get binding value (return null when not present)
        var propertyName = bindingContext.ModelName;
        var originalValueResult = bindingContext.ValueProvider.GetValue(propertyName);
        if (originalValueResult == null)
            return null;
        var boundValue = originalValueResult.AttemptedValue;

        // Trim when required
        if (!String.IsNullOrEmpty(boundValue))
        {
            // Check for trim attribute
            if (bindingContext.ModelMetadata.ContainerType != null)
            {
                var property = bindingContext.ModelMetadata.ContainerType.GetProperties()
                    .FirstOrDefault(propertyInfo => propertyInfo.Name == bindingContext.ModelMetadata.PropertyName);
                if (property != null && property.GetCustomAttributes(true)
                    .OfType<StringTrimAttribute>().Any())
                {
                    // Trim when attribute set
                    boundValue = boundValue.Trim();
                }
            }
        }

        // Register updated "attempted" value with the model state
        bindingContext.ModelState.SetModelValue(propertyName, new ValueProviderResult(
            originalValueResult.RawValue, boundValue, originalValueResult.Culture));

        // Return bound value
        return boundValue;
    }
}

Si vous ne définissez pas la valeur de la propriété dans le classeur, même lorsque vous ne voulez pas changer quoi que ce soit, vous allez bloquer cette propriété de ModelState tout à fait! C'est parce que vous êtes inscrit à titre de liaison de tous les types de chaînes, de sorte qu'il apparaît (dans mes tests) que le classeur par défaut ne le fera pas pour vous, alors.

5voto

Eric Nelson Points 143

Tout en parcourant les excellentes réponses et les commentaires ci-dessus et de plus en plus confus, j’ai soudain pensé, Hé, que je me demande si il existe une solution de jQuery. Donc pour ceux qui, comme moi, trouve ModelBinders un peu déroutante, je vous offre l’extrait suivant de jQuery qui tronque les champs d’entrée avant que le formulaire est envoyé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X