0

クラスがあります(簡素化されたバージョン):

public class Parameter
{
    public Guid Id { get; set; }

    public decimal Value { get; set; }
}

私の見解では、パラメーターの辞書があり、次のようにレンダリングされます。

<input ... name="Parameters[3].Key" type="hidden" value="UniqueParamName" />
<input ... name="Parameters[3].Value.Id" type="hidden" value="395816ad-dfde-11e1-8c36-848f69f05f09" />
<input ... name="Parameters[3].Value.Value" type="text" value="75" />

検証ルールは、いくつかの GUI を介してユーザーが設定し、データベースに保存されます。for currentでValidationAttributeデータベースから sを取得したいのですが、それを行う方法がわかりません。また、いくつかの [厄介な] リフレクションを介してコンテナーにアクセスできる に属性を追加しようとしましたが、「値」のメタデータが作成されているときに「ID」がまだ割り当てられていません (とにかく、信頼できません)。全体を複雑にしすぎているのかもしれませんが、組み込みの検証に固執したいだけです。Parameter.IdParameter.ValueModelMetadataProvider.CreateMetadata

public class ExtendedValidationProvider : DataAnnotationsModelValidatorProvider
{
    protected override IEnumerable<ModelValidator> GetValidators(
        ModelMetadata metadata, 
        ControllerContext context, 
        IEnumerable<Attribute> attributes)
    {
        if (metadata.ContainerType == typeof(Parameter) 
            && metadata.PropertyName == "Value")
        {
            Guid parameterId = <some magic code>;
            IEnumerable<Attribute> validationAttributes 
                = db.GetValidationAttributesByParameterId(parameterId);
            return base.GetValidators(metadata, context, validationAttributes);
        }

        return Enumerable.Empty<ModelValidator>();
    }
}
4

2 に答える 2

0

私の意見では、モデル検証を使用する必要があります。モデル検証は、モデルと、モデルで定義された検証属性で適用されたルールに対して検証します。

public class MyModel
{
     // This model uses model validation

     [Required(ErrorMessage = "FirstName is a required field.")]
     [StringLength(50, ErrorMessage = "Your FirstName can not exceed 50 characters.")]
     public string FirstName { get; set; }

     [Required(ErrorMessage = "LastName is a required field.")]
     public string LastName { get; set; }
}

これにより、検証用のモデルが設定されます。次に、コントローラー/アクションで、ModelState.IsValidを使用してModelStateを検証する必要があります。コントローラーでカスタムの「検証」を実行し、ModelStateのAddModelErrorを使用してカスタムエラーを追加することもできます。

さらに一歩進んで独自の検証属性を作成したい場合は、ValidationAttributeクラスから継承された新しいクラスを作成するだけです。これにより、DAL層にある可能性のある独自の値、またはモデルにバインドされた別の値に対して検証できます。

モデル検証を使用すると、グローバリゼーションを使用する必要がある場合にも、定義したさまざまな言語のリソース文字列を含むリソースファイルを選択できる属性があるため、適切に(そして簡単に)設定できます。

私はこれをメモリから行っていますが、これにより、MVC3の組み込み機能を使用し、モデルのバインドとモデルの状態を利用する正しい方向に進むはずです。

HTH

于 2012-08-15T19:55:24.840 に答える
0

次のように、カスタム ModelMetadataProvider にコンテナーを設定できると考えました。

public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor,
    Type containerType, string propertyName)
{
    var metadata = _InnerProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName);
    if (containerType == typeof(Parameter) 
        && !metadata.AdditionalValues.ContainsKey("container"))
    {
        metadata.AdditionalValues["container"] = GetContainer(modelAccessor);
    }

    return metadata;
}

GetContainerその[厄介な]リフレクション(実際には、コンパイルおよびキャッシュされた式)を使用するメソッドです。

最後に、検証プロバイダー側​​にマジック コードはありません。

public class ExtendedValidationProvider : DataAnnotationsModelValidatorProvider
{
    protected override IEnumerable<ModelValidator> GetValidators(
        ModelMetadata metadata, 
        ControllerContext context, 
        IEnumerable<Attribute> attributes)
    {
        if (metadata.ContainerType == typeof(Parameter) 
            && metadata.PropertyName == "Value")
        {
            Guid parameterId = ((Parameter)metadata.AdditionalValues["container"]).Id;
            IEnumerable<Attribute> validationAttributes 
                = db.GetValidationAttributesByParameterId(parameterId);
            return base.GetValidators(metadata, context, validationAttributes);
        }

        return Enumerable.Empty<ModelValidator>();
    }
}
于 2012-08-17T12:42:19.350 に答える