から継承する MVC 4 用のカスタム モデル バインダーを構築しようとしていDefaultModelBinder
ます。任意のバインディング レベルで任意のインターフェイスをインターセプトし、 という非表示フィールドから目的の型をロードしようとしますAssemblyQualifiedName
。
これが私がこれまでに持っているものです(簡略化):
public class MyWebApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
ModelBinders.Binders.DefaultBinder = new InterfaceModelBinder();
}
}
public class InterfaceModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
if (bindingContext.ModelType.IsInterface
&& controllerContext.RequestContext.HttpContext.Request.Form.AllKeys.Contains("AssemblyQualifiedName"))
{
ModelBindingContext context = new ModelBindingContext(bindingContext);
var item = Activator.CreateInstance(
Type.GetType(controllerContext.RequestContext.HttpContext.Request.Form["AssemblyQualifiedName"]));
Func<object> modelAccessor = () => item;
context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);
return base.BindModel(controllerContext, context);
}
return base.BindModel(controllerContext, bindingContext);
}
}
Create.cshtml ファイルの例 (簡略化):
@model Models.ScheduledJob
@* Begin Form *@
@Html.Hidden("AssemblyQualifiedName", Model.Job.GetType().AssemblyQualifiedName)
@Html.Partial("_JobParameters")
@* End Form *@
上記のパーシャルは のプロパティを_JobParameters.cshtml
調べてModel.Job
、 と同様に編集コントロールを作成しますが、@Html.EditorFor()
追加のマークアップがあります。ScheduledJob.Job
プロパティはタイプ(IJob
インターフェース) です。
例 ScheduledJobsController.cs (簡略化):
[HttpPost]
public ActionResult Create(ScheduledJob scheduledJob)
{
//scheduledJob.Job here is not null, but has only default values
}
フォームを保存すると、オブジェクト タイプが正しく解釈され、新しいインスタンスが取得されますが、オブジェクトのプロパティが適切な値に設定されていません。
指定された型のプロパティ バインディングを引き継ぐように既定のバインダーに指示するには、これに対して他に何をする必要がありますか?