【问题标题】:ASP.NET MVC Wizard issueASP.NET MVC 向导问题
【发布时间】:2013-06-22 06:51:16
【问题描述】:

您好,我使用这篇文章在 asp.net mvc 中创建了一个向导: multi-step registration process issues in asp.net mvc (splitted viewmodels, single model)

它仅适用于接口后面具体类的数据注释 IStepViewModel

是否可以在 StepViewModelBinder 中添加一些功能以在具体步骤上执行模型绑定器?

提前致谢

【问题讨论】:

    标签: asp.net asp.net-mvc wizard modelbinder


    【解决方案1】:

    找到了解决办法。不幸的是,它不像原来的那样通用 - 但它允许视图模型的模型绑定器。

    我将原来的 StepViewModelBinder 替换为以下内容:

     public class StepViewModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            var stepTypeValue = bindingContext.ValueProvider.GetValue("StepType");
            var stepType = Type.GetType((string)stepTypeValue.ConvertTo(typeof(string)), true);
            var step = Activator.CreateInstance(stepType);
    
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => step, stepType);
            return step;
        }
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            //bind using default binding, and calls the overriden "CreateModel"
            var model = base.BindModel(controllerContext, bindingContext);
    
            //if the modelstate is not valid return to controller with found error
            if (!bindingContext.ModelState.IsValid)
                return model;
    
            //if the modelstate is valid, call the modelbinder for the concreteType
            var ll = Binders.GetBinder(model.GetType());
            return ll.BindModel(controllerContext, bindingContext);
        }
    
    }
    

    此解决方案为模型获取关联的模型绑定器 - 缺点是,由于具体实现隐藏在接口后面,因此模型绑定器需要才能用于具体实现,因为具体类型不能从接口实例化

    具体类的模型绑定器可能如下所示:

      protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            var step = new Step1();
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => step, step.GetType());
            return step;
        }
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var model = (Step1)base.BindModel(controllerContext, bindingContext);
            bindingContext.ModelState.AddModelError("", "This is a test");
            return model;
        }
    

    modelbinder 像往常一样与 viewmodel 耦合在一起,要么通过

    ModelBinders.Binders.Add(typeof(Step1), new Step1ModelBinder());
    

    或通过类注解:

    [ModelBinder(typeof(OpretBrugerStep1ModelBinder))]
    

    我刚刚为不需要特定实现的步骤实现创建了一个通用的默认模型绑定器 - 只是为了让它们与示例一起工作:

    public class DefaultStepModelBinder<T> : DefaultModelBinder where T : IStepViewModel, new()
        {
            protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
            {
                var step = new T();
                bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => step, step.GetType());
                return step;
            }
            public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                var model = (T)base.BindModel(controllerContext, bindingContext);
                return model;
            }
        }
    

    因此,具体步骤可以使用此模型绑定器 - 以 step1 为例:

     [ModelBinder(typeof(DefaultStepModelBinder<Step1>))]
    [Serializable]
    public class Step1 : IStepViewModel
    { ... }
    

    【讨论】:

    • 我刚刚为不需要特定实现的步骤实现创建了一个通用的默认模型绑定器 - 只是为了让它们与示例一起工作:
    猜你喜欢
    • 2013-03-27
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    • 2011-11-17
    • 2010-11-03
    相关资源
    最近更新 更多