MVC2 Action to handle multiple models

℡╲_俬逩灬. 提交于 2019-12-24 19:02:13

问题


I've been looking around for an answer to this, which I can't believe hasn't been asked before, but with no luck I'm attempting here.

I have a signup form which differs slightly based upon what type of participant the requester is. While writing tests for the solution, I realized that all actions did the same things, so I'm attempting to combine the actions into one using a strategy pattern.

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 }

Here is the combined action:

[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());
}

The problem I'm having is that TryUpdateModel binds only the common properties found in BaseForm. My previous code used public ActionResult FormName(int id, FormX form) which bound properly. However, I did some testing and discovered that if I replace var form with FormX form the form binds and everything works, but I'm back to one action per form type.

I'm hoping to find a way to get this to bind properly. form.GetType() returns the proper non-base class of the form, but I'm not sure of how to grab the constructor, instantiate a class, and then throw that into TryUpdateModel. I know that the other possibility is a custom ModelBinder, but I don't see a way of creating one without running into the same FormBase problem.

Any ideas or suggestions of where to look?


回答1:


I was trying to do something similar to Linq, I was trying to create a class that would inherit some standard fields (ID, etc). I found that the default Linq engine would only use fields from the instantiated class, not from any inherited classes or interfaces.

To construct a Type simply use code like:

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



回答2:


I figured it out!

Erik's answer wasn't the solution, but for some reason it made me think of the solution.

What I really want form to be is a dynamic type. If I change this line:

dynamic form = uiWrapper.GetForm();

Everything works :)

On top of that, logic.Save(form.ToDomainClass()) also goes directly to Save(DomainTypeOfForm) rather than Save(BaseDomainForm) so I can avoid the headache there as well. I knew that once I figured out the problem here I could apply the answer in my logic class as well.



来源:https://stackoverflow.com/questions/3603211/mvc2-action-to-handle-multiple-models

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!