2

ステップ(コントローラー)を備えたウィザードのようなものを開発しており、継承し、追加のプロパティでそれらを拡張するなどを使用DerivedModel1DerivedModel2BaseModelいます。モデル - データのみ、ビジネス ロジックなし。_step1Service.GetRelated(model.id) などのコントローラー アクションでサービスによって実行されるすべてのロジック。

ここで、モデルを検証するだけでなく (この場合は がありますValidationAttribute)、無効なデータを修正したいと思いますBaseModel:

 public class BaseModel
 {
     public DateTime StartDate {get;set;}
 }

StartDate今日よりも大きくなるはずです。ユーザーは無効な日付を選択でき、検証エラーの代わりに、アプリケーションはこの値を修正する必要があります (デフォルトにリセットしますか?)。

私の最初の試みでは、検証/修正のためのサービスを追加StartDateし、各アクションで呼び出しました。

public ActionResult Index(DerivedModel1 model)
{
_svc.fixModel(model);

if(!ModelState.IsValid)
{
return View();
}

... do stuff with valid data
}

しかし、この行を各コントローラーとアクションに追加する必要があるため、それは好きではありません。次に、この修正をStartDateセッターに追加します。見栄えは良くなりますが、これはすべてのロジックをコントローラーに配置する必要があるという一般的な MVC パラダイムを破っています (または、何か誤解しているのでしょうか?) この問題の可能な解決策について考えていました: ActionFilterAttribute、カスタム ModelBinder? しかし、これが正しい方法であり、機能するかどうかはわかりません。それについてどう思いますか?

4

2 に答える 2

1

これを実現するには、IModelBinder を実装する必要があります。

最初にカスタム モデル バインダーを次のように定義します。

public class MyCustomModelBinder : IModelBinder
{
   public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            // Get the raw attempted value from the value provider
            DateTime incomingDate = (DateTime) bindingContext.ValueProvider.GetValue("datefield").AttemptedValue;
            //validate and correct date here ...
            return new BaseModel{ DateMember =  incomingDate };
        }
}

次に、次のようなカスタム モデル バインダーを登録します。

protected void Application_Start()
{
       ModelBinders.Binders.Add(typeof (BaseModel), new MyCustomModelBinder());          
}

そしてあなたのコントローラー:

public ActionResult YourAction([ModelBinder(typeof(MyCustomModelBinder )] BaseModel model)
{
      return Content("Ok");
}
于 2012-11-22T18:08:57.493 に答える
0

検証とビジネス ルールには違いがあります。オブジェクトは、それ自体が有効な状態であることを確認する責任があります (多くの場合、そうあるべきです)。

于 2012-11-22T17:54:58.787 に答える