ASP.NET MVC向导问题

时间:2013-06-25 12:55:06

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

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

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

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

提前致谢

1 个答案:

答案 0 :(得分:0)

找到解决方案。 Unfornutanely它不是原始的通用 - 但它允许视图模型的模型绑定器。

我用以下内容替换了原始的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;
    }

模型绑定器通常通过

与视图模型耦合在一起
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;
        }
    }

因此具体步骤可以使用这个模型绑定器 - 步骤1的例子:

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