2013-07-17 11 views
6

Ich arbeite in MVC4 und möchte ein Modell mit einem Uppercase Attribut definieren. Die Idee wäre, dass das Vorhandensein des Uppercase-Attributs dazu führen würde, dass der Modellwert beim Eintreffen am Server in Großbuchstaben konvertiert wird.Großbuchstaben-Attribut, das die Eingabe in Großbuchstaben umwandelt

Im Moment habe ich den folgenden Code innerhalb des Modells haben:

[Required] 
    [Display(Name="Account Code")] 
    [StringValidation(RegExValidation.AccountCode, Uppercase=true)] 
    public string Account 
    { 
     get { return _account; } 
     set 
     { 
      if (value != null) 
       _account = value.ToUpper(); 
     } 
    } 

Aber was würde Ich mag, ist dies:

[Required] 
    [Display(Name="Account Code")] 
    [StringValidation(RegExValidation.AccountCode)] 
    [Uppercase] 
    public string Account { get; set; } 

Ich denke, dass ich das Versalien- Attribut erstellen müssen können als ValidationAttribute um sicherzustellen, dass es ausgelöst wird, wenn das Modell den Server trifft. Aber das scheint ein bisschen falsch zu sein, da ich die Daten nicht wirklich validiere. Gibt es einen besseren Weg?

Gibt es auch eine Möglichkeit, die Aufrufreihenfolge für die Attribute zu gewährleisten? Ich möchte die Daten wirklich in Großbuchstaben konvertieren, bevor das benutzerdefinierte Attribut StringValidation ausgelöst wird, da dies den Fall des Textes im Regex-Muster überprüft.

Um ein wenig Hintergrund hinzuzufügen, möchte ich die Notwendigkeit reduzieren, den Großbuchstaben der Daten Code hinzuzufügen. Das Nirvana wäre ein einzelnes Attribut, das die Daten auf dem Weg zum Server entweder in der Modellbindungs- oder Validierungsphase aktualisiert. Auf dieses Attribut kann dann im Attribut StringValidation verwiesen werden, um den bei seinen Prüfungen verwendeten RegEx-Wert zu ändern. Ich kann dieses Attribut auch in einer benutzerdefinierten TextBoxFor Hilfsmethode nachschlagen, so dass ich text-transform: uppercase hinzufügen kann, damit es auf der Clientseite korrekt aussieht.

Hat jemand irgendwelche Ideen da draußen?

Antwort

5

Ich habe es geschafft, das funktioniert zu einem gewissen Punkt, also hier ist meine Lösung für andere zu schätzen.

Sobald Punkt zu beachten war, dass die vollständige Lösung nicht erreicht werden konnte, weil ich nicht die Modelmetadata innerhalb der StringValidation.IsValid() Attribut bekommen konnte. Das besondere Problem, das ich hier hatte, war, dass ich die Metadaten bekommen konnte, aber ich konnte nicht die PropertyName davon bekommen, nur die DisplayName. Es gab mehrere Optionen da draußen, aber die Tatsache, dass einige meiner Eigenschaften die gleiche DisplayName haben, bedeutet, dass ich nicht sicher sein konnte, dass die ProprtyName die war, die ich tatsächlich validierte.

Hier ist der Code für die ValidationAttribute:

public class StringValidationAttribute : ValidationAttribute, IClientValidatable, IMetadataAware { 

    private bool _uppercase; 

    public StringValidationAttribute(bool uppercase = false) { 
     _uppercase = uppercase; 
    } 

    ... 

    public void OnMetadataCreated(ModelMetadata metadata) 
    { 
     metadata.AdditionalValues["Uppercase"] = _uppercase; 
    } 
} 

Ich habe dann eine neue IModelBinder Implementierung:

public class StringBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {   
     ValueProviderResult result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     if (result == null) 
      return null; 

     if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey("Uppercase")) { 
      if ((bool)bindingContext.ModelMetadata.AdditionalValues["Uppercase"]]) 
       return result.AttemptedValue.ToUpper(); 
     } 

     return result.AttemptedValue; 
    } 
} 

Und registriert, dass in meiner Global.asax Datei:

ModelBinders.Binders.Add(typeof(string), new StringBinder()); 

Der Code so weit wird jeder String Eingabe Co verursachen ming in MVC, um in Großbuchstaben konvertiert zu werden, wenn StringValidationAttribute an das Modell angehängt ist und der Großbuchstabenindikator gesetzt wurde.

Als nächstes, um meinen Wunsch zu erreichen, die HTML-Formulare auch Großbuchstaben zu machen, implementierte ich eine neue 10 namens . In dieser Ansicht habe ich hinzugefügt:

RouteValueDictionary htmlAttributes = new RouteValueDictionary(); 
if ((bool)ViewData.ModelMetadata.AdditionalValues["Uppercase"]) { 
    htmlAttributes.Add("class", "Uppercase"); 
} 
@Html.TextBox("", Model, htmlAttributes) 

Mit dem CSS als;

.Uppercase { 
    text-transform: uppercase; 
} 

Hoffe, dieser Beitrag hilft einigen anderen da draußen.

+0

Das ist ziemlich cool! –

+0

Hallo, gilt das für MVC 4? weil ich folgenden Fehler erhalte. 'UpperCaseValidationAttribute' implementiert kein Interface-Member 'System.Web.Mvc.IClientValidatable.GetClientValidationRules (System.Web.Mvc.ModelMetadata, System.Web.Mvc.ControllerContext)' Könnten Sie bitte helfen? Vielen Dank!! – ecasper

+0

Ja, das funktioniert in MVC4. Sie müssen eine Überschreibung für 'public IEnumerable GetClientValidationRules (ModelMetadata-Metadaten, ControllerContext-Kontext) hinzufügen'. Dies war das Bit in der ... in der Antwort :) – Nick

0

Sie haben Recht, ValidationAttribute ist nicht die richtige Passform. Es scheint, als wäre es eine bessere Idee, dies in der Modellbindungsstufe zu tun. Eine detaillierte Erläuterung zum Anpassen dieses Verhaltens finden Sie unter this article.

Auf der Grundlage der dort bereitgestellten Informationen, ich glaube, Sie sollten in der Lage ein Attribut basierend auf CustomModelBinderAttribute wie diese zu erstellen:

[AttributeUsage(AttributeTargets.Property)] 
public class UppercaseAttribute : CustomModelBinderAttribute 
{ 
    public override IModelBinder GetBinder() 
    { 
     return new UppercaseModelBinder(); 
    } 

    private class UppercaseModelBinder : DefaultModelBinder 
    { 
     public override object BindModel(
      ControllerContext controllerContext, 
      ModelBindingContext bindingContext) 
     { 
      var value = base.BindModel(controllerContext, bindingContext); 
      var strValue = value as string; 
      if (strValue == null) 
       return value; 
      return strValue.ToUpperInvariant(); 
     } 
    } 
} 

ich nicht getestet haben. Lass es mich wissen, ob es funktioniert oder nicht.

+0

Dank Daniel, leider kann der DefaultModelBinder nicht den Eigenschaften zugewiesen werden. 'AttributeUsageAttribute (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Parameter' – Nick

+0

Dann müssen wir eine Stufe höher gehen.Wir müssen den Modellbinder für die Klassen ändern, die diese Zeichenfolgen enthalten, das UppercaseAttribute in ein einfaches Markierungsattribut ändern und dem Modellbinder mitteilen, nach diesem Attribut zu suchen und diese Zeichenfolgen unterschiedlich zu behandeln. –

-1

HINWEIS: Ich bin auf diesen Beitrag hinzufügen, weil, bis ich den Ansatz, den ich jetzt benutze, ich lese das und versuchte alle oben erfolglos.

Ich verwende in der Regel einen zweiteiligen Prozess, wenn es darum geht, Textdaten als Großbuchstaben zu formatieren. 1. in der Ansicht und 2. bei der Steuerung An der View-Schicht

  1. so dass die Benutzerdaten kennen in der Großform verwendet werden sollen. Dies kann durch htmlAttributes geschehen, die im EditorFor HTML-Helper verwendet werden.

    @HTML.EditorFor(model => model.Access_Code, new { htmlAttributes = new Style= "text-transform:uppercase"}}) 
    

Nun zwingt dies nur die Daten durch den Benutzer die Daten in Großbuchstaben und nicht an den Server gesendet gesehen und trat ein. Dazu ist Code in der zugeordneten Methode im Controller erforderlich.

  1. Ich füge die Methode ToUpper() zum Zielattribut des Objekts hinzu, das an den Controller zurückgegeben wird. Hier ist ein hypothetisches Beispiel, das dies zeigt.

    public ActionResult verify(int? id) 
         { 
         var userData = db.user.Where (i=> i.userID == id).Single(); 
    
         userData.Access_Code = userData.Access_Code.ToUpper(); 
    
        ... 
    } 
    
0

für Web-API Zweck ist es besser, die eingehenden json konvertieren in Groß- oder Kleinbuchstaben.

public class ToUpperCase : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return objectType == typeof(string); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return reader.Value.ToString().ToUpper(); 
     }    
    } 



    [Display(Name = "PNR NAME")] 
    [JsonConverter(typeof(Annotations.ToUpperCase))] 
    public string PNR { get; set; } 

ODER global;

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 
     //.......... others 



     JsonMediaTypeFormatter jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter; 
     JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings(); 
     jSettings.Converters.Add(new UpperCaseStringConverter()); 
     jsonFormatter.SerializerSettings = jSettings; 
    } 
Verwandte Themen