【问题标题】:MVC2 Action to handle multiple modelsMVC2 Action 处理多个模型
【发布时间】:2010-08-30 18:39:52
【问题描述】:

我一直在寻找这个问题的答案,我不敢相信以前没有人问过这个问题,但没有运气我在这里尝试。

我有一个注册表单,根据请求者的参与者类型而略有不同。在为解决方案编写测试时,我意识到所有动作都做同样的事情,因此我尝试使用策略模式将这些动作组合成一个。

public abstract class BaseForm { common properties and methods }
public class Form1 : BaseForm { unique properties and overrides }
....
public class FormX : BaseForm { unique properties and overrides... in all about 5 forms }

以下是组合操作:

[ModelStateToTempData, HttpPost]
public ActionResult Signup(int id, FormCollection collection)
{
    uiWrapper= this.uiWrapperCollection.SingleOrDefault(w => w.CanHandle(collection));
    // nullcheck on uiWrapper, redirect if null
    var /*BaseForm*/ form = uiWrapper.GetForm();  // Returns FormX corresponding to collection.
    this.TryUpdateModel(form, collection.ToValueProvider()); // Here is the problem
    form.Validate(this.ModelState);  // Multi-Property validation unique to some forms.
    if (!this.ModelState.IsValid)
        return this.RedirectToAction(c => c.Signup(id));

    this.Logic.Save(form.ToDomainClass());
    return this.RedirectToAction(c => c.SignupComplete());
}

我遇到的问题是 TryUpdateModel 仅绑定 BaseForm 中的常见属性。我之前的代码使用了正确绑定的 public ActionResult FormName(int id, FormX form) 。但是,我做了一些测试,发现如果我用 FormX 表单替换 var 表单,表单绑定并且一切正常,但是我回到了每种表单类型的一个操作。

我希望找到一种方法来使其正确绑定。 form.GetType() 返回表单的正确非基类,但我不确定如何获取构造函数,实例化一个类,然后将其放入 TryUpdateModel。我知道另一种可能性是自定义 ModelBinder,但我没有看到一种方法可以在不遇到相同 FormBase 问题的情况下创建它。

关于去哪里看有什么想法或建议吗?

【问题讨论】:

  • 好吧,我想出了如何获取构造函数: var typedForm = form.GetType().GetConstructors().Where(c => c.GetParameters().Length == 0).Single ().Invoke(null);不幸的是,返回类型 Object 和 TryUpdateModel 返回更少的绑定:(
  • 非常有趣:var typedForm = form as FormX; this.TryUpdateModel(typedForm, collection.ToValueProvider());作品!现在,如果我能找到一种通用的方法......

标签: asp.net-mvc-2 model-binding


【解决方案1】:

我试图做一些类似于 Linq 的事情,我试图创建一个继承一些标准字段(ID 等)的类。我发现默认的 Linq 引擎只会使用来自实例化类的字段,而不是来自任何继承的类或接口。

要构造Type,只需使用如下代码:

var form = Activator.CreateInstance(uiWrapper.GetForm()); 

【讨论】:

  • var form = Activator.CreateInstance(uiWrapper.GetForm().GetType());确实授予我一个表单,但不幸的是,它当时被装箱为 Object 并且 form.Validate(this.ModelState) 不再是有效的方法调用。感谢您的尝试。
【解决方案2】:

我想通了!

Erik 的回答不是解决方案,但出于某种原因,它让我想到了解决方案。

我真正想要的形式是动态类型。如果我改变这一行:

dynamic form = uiWrapper.GetForm();

一切正常 :)

最重要的是, logic.Save(form.ToDomainClass()) 也直接转到 Save(DomainTypeOfForm) 而不是 Save(BaseDomainForm) 所以我也可以避免那里的头痛。我知道,一旦我发现了这里的问题,我也可以将答案应用到我的逻辑课中。

【讨论】:

  • 1) 将我自己的答案标记为解决方案是否被认为是不好的形式? 2) Erik,如果您使用的是 C# 4.0,我希望这个解决方案也能解决您的问题。
  • 将此标记为答案,我完全忘记了动态,因为我刚开始工作,我们仍在使用 3.5!
猜你喜欢
  • 1970-01-01
  • 2020-11-26
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多