2011-08-25 6 views
5

強く型付けされたビューにDropDownListFor属性があります。Guidの検証

ドロップダウンリストの各項目は、GUIDで表されます。

ユーザーがドロップダウンリストからアイテムを選択した場合に検証する方法です。現在私はData Annotationsを使ってこれをやっているとは思わない。

データ注釈を使用してこれを達成しても、クライアント側とサーバー側の検証が機能することはありますか。

私はこれを行うカスタムメソッドを作る必要があると思っていますが、何かが存在するかどうか疑問に思っていました。

答えて

8

編集回答の際

再読み込みしたばかりの値が選択されているかどうかを知りたいようなあなたの質問を、それが聞こえます。その場合はその後、ちょうどRequiredAttributeからGuidプロパティを適用し、(@model GuidModelに)強く型付けされたビューで

public class GuidModel 
{ 
    [Required] 
    public Guid? Guid { get; set; } 

    public IEnumerable<Guid> Guids { get; set; } 
} 

そのモデルに、それはNULL可能にする

@Html.ValidationMessageFor(m => m.Guid) 
@Html.DropDownListFor(
    m => m.Guid, 
    Model.Guids.Select(g => new SelectListItem {Text = g.ToString(), Value = g.ToString()}), 
    "-- Select Guid --") 

クライアント検証JavaScriptスクリプトを追加します。クライアント側の検証のための参照。

コントローラは、これはGuidプロパティはモデル結合GuidModelのために必要であることを保証します

public class GuidsController : Controller 
{ 
    public GuidRepository GuidRepo { get; private set; } 

    public GuidsController(GuidRepository guidRepo) 
    { 
     GuidRepo = guidRepo; 
    } 

    [HttpGet] 
    public ActionResult Edit(int id) 
    { 
     var guid = GuidRepo.GetForId(id); 
     var guids - GuidRepo.All(); 

     return View(new GuidModel { Guid = guid, Guids = guids }); 
    } 

    [HttpPost] 
    public ActionResult Edit(GuidModel model) 
    { 
     if (!ModelState.IsValid) 
     { 
      model.Guids = GuidRepo.All(); 
      return View(model); 
     } 

     /* update db */ 

     return RedirectToAction("Edit"); 
    } 
} 

のように見えます。

オリジナル回答

私はこれを行うことが可能である既製のデータ注釈検証属性があることを信じていません。私はa blog post about one way to achieve thisと書いた。ポストはIoCコンテナを使用していますが、何か動作したい場合はハードコーディングされた依存関係を取ることができます。

public class ValidGuidAttribute : ValidationAttribute 
{ 
    private const string DefaultErrorMessage = "'{0}' does not contain a valid guid"; 

    public ValidGuidAttribute() : base(DefaultErrorMessage) 
    { 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var input = Convert.ToString(value, CultureInfo.CurrentCulture); 

     // let the Required attribute take care of this validation 
     if (string.IsNullOrWhiteSpace(input)) 
     { 
      return null; 
     } 

     // get all of your guids (assume a repo is being used) 
     var guids = new GuidRepository().AllGuids(); 

     Guid guid; 
     if (!Guid.TryParse(input, out guid)) 
     { 
      // not a validstring representation of a guid 
      return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
     } 

     // is the passed guid one we know about? 
     return guids.Any(g => g == guid) ? 
      new ValidationResult(FormatErrorMessage(validationContext.DisplayName)) : null; 
    } 
} 

して、モデルのような

何かが、あなたはこれがあなたに、サーバー側の検証を与えるコントローラのアクション

public class GuidModel 
{ 
    [ValidGuid] 
    public Guid guid { get; set; } 
} 

に送ります。 RemoteAttributeを使用して、これを行うクライアント側の検証を記述することもできますが、このクライアント側の検証を見ようとしている唯一の人は、 DOM;あなたの普通のユーザーには何のメリットもありません。

+1

Guidプロパティにnullableとマークしない限り、実際には機能しません。私の答えを参照してください。 –

+0

@NickAlbrechtありがとう、 –

15

実際にはstructから継承しているため、Required属性をGUIDに使用することはできません。これらの値は実際にはGuid.Emptyのインスタンスであり、実際にはRequired属性です。今言われているように、あなたが望むものを得ることは、あなたのプロパティをnullableにする必要があるだけです。たとえばこれを取る...GUIDのNULL可能マークを付けることによって

public class Person 
{ 
    [Required] //Only works because the Guid is nullable 
    public Guid? PersonId { get; set;} 
    public string FirstName { get; set;} 
    public string LastName { get; set;} 
} 

(?使用して、またはNull許容あなたは長い道のりを好む場合)には、ブラウザが送信したものに対して結合するとき、それがnullとして滞在してみましょう。あなたの場合、ドロップダウンのデフォルトオプションの値が空の文字列を値として使用していることを確認してください。

EDIT:このメソッドへの唯一の注意点は、あなたがどこでもPerson.GetValueOfDefault()ようなものを使用することで潜在的にGuid.Emptyのためにテストを終了している。私はこれに疲れて、Guid(およびint、DateTimeなど無効と扱うデフォルト値を持つ他の型)の検証を簡素化するための独自の検証属性を作成しました。しかし、私はこれに伴ってクライアント側の検証をまだ行っていないので、検証はサーバー上でのみ行われます。ただし、null可能な型を使用しても問題がなければ、これは[Required][Required]の機能を複製しないように設計されている)と組み合わせることができます。少なくとも、[Required]のクライアント側の検証を取得します。これはあなたがまだGetValueOrDefault()を使用しなければならないことを意味しますが、少なくともあなたはGuid.Emptyをもうテストする必要はありません。 Gistのリンクにはいくつかの例があるXMLDocがありますが、ここでは簡潔にするためにそれらを残しました。私は現在ASP.NET Coreでそれを使用しています。

要旨:RequireNonDefaultAttribute

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] 
public class RequireNonDefaultAttribute : ValidationAttribute 
{ 
    public RequireNonDefaultAttribute() 
     : base("The {0} field requires a non-default value.") 
    { 
    } 

    public override bool IsValid(object value) 
    { 
     return value != null && !Equals(value, Activator.CreateInstance(value.GetType())); 
    } 
} 
+0

私は以下のようなモデルであなたのコードを使用しようとしましたが、モデルがnull値を供給すると失敗しますか?私はnullが大丈夫だと思っていますが、この場合は要約の例によると0ではありません。 [必須ではない]を確認してください public int?テスト{取得;セット; } – Krishna

+0

あなたのタイプが 'int? 'Nullable <>'オブジェクトのデフォルト値はnullなので、nullは有効ではありませんが、0が有効です。しかし、あなたは私の例がそうでないことを意味するのは正しいです。私はそれを修正します。あなたが何をしているのかを知るには(nullではなく、0ではなく)、この[[Range(1、int.MaxValue)] intのようなものを使う方が良いでしょうか? i {get; set;} ' –

+0

@Alberchtご確認ありがとうございます。 – Krishna

3

私は、これは今、古い質問ですけど、誰にも興味を持っている場合、私は[IsNotEmpty]注釈(GUIDのNULL可能ではありませんでし作りを作成することによってこの問題を回避するために管理私の場合はオプション)。

これは、プロパティにEmptyの実装があるかどうかを調べるためにリフレクションを使用します。

public class IsNotEmptyAttribute : ValidationAttribute 
{ 

    public override bool IsValid(object value) 
    { 

     if (value == null) return false; 

     var valueType = value.GetType(); 
     var emptyField = valueType.GetField("Empty"); 

     if (emptyField == null) return true; 

     var emptyValue = emptyField.GetValue(null); 

     return !value.Equals(emptyValue); 

    } 
}