开发者

MVC2 Action to handle multiple models

开发者 https://www.devze.com 2023-01-14 05:47 出处:网络
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'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?


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消