A 从已经工作的 CustomModelBinder 创建了一个新的 CustomModelBinder。为什么新的永远不会被调用来进行任何绑定?

发布于 2024-11-26 14:43:03 字数 2343 浏览 2 评论 0原文

我可以做这样的事情吗?

[HttpPost]
public ActionResult Index(WizardViewModel wizard, IStepViewModel step)
{

中有以下内容

    ModelBinders.Binders.Add(typeof(IStepViewModel), new StepViewModelBinder());
    ModelBinders.Binders.Add(typeof(WizardViewModel), new WizardViewModelBinder());

我的 global.asax.cs application_start更新

所以,我试图看看出了什么问题。这是我的新代码。问题似乎出在这个 WizardViewModel 及其活页夹上。什么“告诉”应用程序期望和传入的向导模型?

[HttpPost]
public ActionResult Index(WizardViewModel wizard)
{

我的 global.asax.cs application_start 中有以下内容

    ModelBinders.Binders.Add(typeof(WizardViewModel), new WizardViewModelBinder());

完整的 Binder 代码

namespace Tangible.Binders
{
    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 class WizardViewModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
                var wizardValue = bindingContext.ValueProvider.GetValue("wizard");
                if (wizardValue != null)
                {
                    var wizardType = Type.GetType((string)wizardValue.ConvertTo(typeof(string)), true);
                    var wizard = Activator.CreateInstance(wizardType);

                    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => wizard, wizardType);
                    return wizard;
                }
                else
                {
                    var wizard = new Tangible.Models.WizardViewModel();
                    wizard.Initialize();
                    return wizard;
                }
        }
    }
}

Can I do something like this?

[HttpPost]
public ActionResult Index(WizardViewModel wizard, IStepViewModel step)
{

Where I have the following in my global.asax.cs application_start

    ModelBinders.Binders.Add(typeof(IStepViewModel), new StepViewModelBinder());
    ModelBinders.Binders.Add(typeof(WizardViewModel), new WizardViewModelBinder());

Update

So, I tried to see what is wrong. Here is my new code. It seems that the problem is with this WizardViewModel and it's binder. What "tells" the application to expect and incoming Wizard model?

[HttpPost]
public ActionResult Index(WizardViewModel wizard)
{

Where I have the following in my global.asax.cs application_start

    ModelBinders.Binders.Add(typeof(WizardViewModel), new WizardViewModelBinder());

Complete Binder Code

namespace Tangible.Binders
{
    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 class WizardViewModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
                var wizardValue = bindingContext.ValueProvider.GetValue("wizard");
                if (wizardValue != null)
                {
                    var wizardType = Type.GetType((string)wizardValue.ConvertTo(typeof(string)), true);
                    var wizard = Activator.CreateInstance(wizardType);

                    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => wizard, wizardType);
                    return wizard;
                }
                else
                {
                    var wizard = new Tangible.Models.WizardViewModel();
                    wizard.Initialize();
                    return wizard;
                }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷默言语 2024-12-03 14:43:04

我过去做过类似的事情,我传递了一个字符串,然后分割了该值。

I have done something similar in the past where I passed a string and then split the value.

素衣风尘叹 2024-12-03 14:43:04

我想说的答案就是:是的!在您的评论中,您担心“许多其他问题”可能会造成麻烦。如果不知道您的想法是什么,就很难为您提供帮助。但您所做的正是模型活页夹的设计目的。没有理由让每个动作只包含一个对象。

I would say the answer is just: Yes! In your comment you are concerned about "many other issues" which might cause trouble. Without knowing what issues you have in mind, it's hard to help you. But what you have done is exactly what model binders are designed for. And there is no reason, why you should have only one object per action.

心不设防 2024-12-03 14:43:04

我对 ASP.NET MVC 模型绑定要求我跳过一些基本的反序列化的障碍感到非常失望。

由于模型绑定并不像我希望的复杂模型/视图模型那样透明,因此我只是构建了一个自定义 ActionFilter 来解析类型[并且仅解析类型],我想在操作方法中反序列化并使用 ServiceStack.Text 满足我所有的序列化/反序列化需求。

看看这里:

https://gist.github.com/3b18a58922fdd8d5a963

I was really disenchanted with the hoops that ASP.NET MVC Model Binding required me to jump through to get some basic deserialization.

Since model binding was no where near as transparent as I had hoped for complex Model / ViewModels I simply built a custom ActionFilter to resolve the types [and ONLY the types] I want to deserialize in the action method and use ServiceStack.Text for all my serialization / deserialization needs.

Take a look here:

https://gist.github.com/3b18a58922fdd8d5a963

梦过后 2024-12-03 14:43:03

答案很简单——是的!当您拥有将值绑定到参数的自定义逻辑时,您应该这样做。您甚至可以使用 ModelBinderAttribute,单独设置每个参数。

    [HttpPost]
    public ActionResult Index([ModelBinder(typeof(WizardViewModelBinder))]WizardViewModel wizard, 
[ModelBinder(typeof(StepViewModelBinder))]IStepViewModel step)
    { }

正如我所见,错误在于您的模型绑定程序代码中。我没有时间检查它,但据我记得,模型绑定器使用 CreateModel 来创建模型的实例,然后返回的实例是模型绑定的。因此,重写 BindModel 而不是 CreateModel 并在 BindModel 中编写模型绑定逻辑。这绝对有效。

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{
//your model binding logic here
}

The answer is simple - Yes! That is what you SHOULD do when you've got custom logic for binding values to your parameters. You can even do that with the use of ModelBinderAttribute, set on each of parameters individually.

    [HttpPost]
    public ActionResult Index([ModelBinder(typeof(WizardViewModelBinder))]WizardViewModel wizard, 
[ModelBinder(typeof(StepViewModelBinder))]IStepViewModel step)
    { }

And as I see, the mistake is in your model binder code. I don't have time to check it up, but as far as i remember, CreateModel is used by model binder to create instance of the model, and then that returned instance is model-binded. So, override BindModel instead of CreateModel and write your model binding logic in BindModel. That definitely works.

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{
//your model binding logic here
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文