【问题标题】:Custom Model Binder inheriting from DefaultModelBinder继承自 DefaultModelBinder 的自定义模型绑定器
【发布时间】:2013-05-20 18:49:00
【问题描述】:

我正在尝试为 MVC 4 构建一个自定义模型绑定器,它将继承自 DefaultModelBinder。我希望它在 any 绑定级别拦截任何接口,并尝试从名为 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
}

当我保存表单时,它会正确解释对象类型并获取一个新实例,但对象的属性没有设置为适当的值。

我还需要做什么来告诉默认绑定器接管指定类型的属性绑定?

【问题讨论】:

    标签: c# asp.net-mvc-4 model-binding


    【解决方案1】:

    This article 向我表明我过于复杂了模型绑定器。以下代码有效:

    public class InterfaceModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType.IsInterface)
            {
                Type desiredType = Type.GetType(
                    EncryptionService.Decrypt(
                        (string)bindingContext.ValueProvider.GetValue("AssemblyQualifiedName").ConvertTo(typeof(string))));
                bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, desiredType);
            }
    
            return base.BindModel(controllerContext, bindingContext);
        }
    }
    

    【讨论】:

    • 你在哪里添加了上面的活页夹?我有活页夹 ModelBinders.Binders.Add(typeof(Organization), new OrganizationModelBinder(DependencyResolver.Current.GetService()));在 App_start() 方法中的 global.asax.cs 页面中。我只是在寻找更好的方法来注册模型绑定器,例如我们如何路由和捆绑?
    • @mmssaann 我在 global.asax.cs Application_Start() 中使用了 ModelBinders.Binders.DefaultBinder = new MyCustomModelBinder();。然后,我使我的 ModelBinder 足够通用以处理任何抽象类或接口,否则将绑定逻辑传递给 DefaultModelBinder。
    【解决方案2】:

    使用 MVC 4 很容易覆盖消息,如果这是您在自定义模型绑定器中可能需要的全部内容:

        protected void Application_Start(object sender, EventArgs e)
        {
            //set mvc default messages, or language specifc
            ClientDataTypeModelValidatorProvider.ResourceClassKey = "ValidationMessages";
            DefaultModelBinder.ResourceClassKey = "ValidationMessages";
        }
    

    然后创建名为ValidationMessages 的资源文件,其条目如下:

    NAME: FieldMustBeDate 
    VALUE: The field {0} must be a date. 
    NAME: FieldMustBeNumeric 
    VALUE: The field {0} must be a number
    

    .

    我们这样做是因为合规失败。我们的安全扫描不喜欢javascript 注入会回来并出现在验证消息中并执行。通过使用此实现,我们将覆盖返回用户提供值的默认消息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 2011-04-25
      • 2012-07-31
      • 1970-01-01
      相关资源
      最近更新 更多