2010-08-30 2 views
0

Я искал ответ на этот вопрос, о котором я не могу поверить, о нем не спрашивали раньше, но мне не повезло, что я пытаюсь здесь.MVC2 Действие для обработки нескольких моделей

У меня есть форма регистрации, которая немного отличается от того, какой тип участника является запрашивающим. При написании тестов для решения я понял, что все действия делали одни и те же вещи, поэтому я пытаюсь объединить действия в один, используя шаблон стратегии.

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. В моем предыдущем коде использовалось общедоступное ActionResult FormName (int id, FormX form), которое правильно привязывалось. Тем не менее, я провел некоторое тестирование и обнаружил, что если я заменю форму var формой FormX, форма связывается, и все работает, но я возвращаюсь к одному действию для типа формы.

Я надеюсь найти способ заставить это правильно связываться. form.GetType() возвращает правильный не-базовый класс формы, но я не уверен, как захватить конструктор, создать экземпляр класса и затем бросить его в TryUpdateModel. Я знаю, что другая возможность - это настраиваемый ModelBinder, но я не вижу способа создать его, не сталкиваясь с той же проблемой FormBase.

Любые идеи или предложения о том, где искать?

+0

Ну, я понял, как получить конструктор: var typedForm = form.GetType(). GetConstructors(). Где (c => c.GetParameters(). Length == 0) .Single(). Invoke (ноль); Это, к сожалению, возвращает тип Object и TryUpdateModel возвращает еще меньше привязки :( – ARM

+0

Очень интересно: var typedForm = form как FormX; this.TryUpdateModel (typedForm, collection.ToValueProvider()); работает! Теперь, если я смогу найти способ сделать это обобщенно .... – ARM

ответ

0

Я понял это!

Ответ Эрика не был решением, но по какой-то причине он заставлял меня думать о решении.

Я хочу, чтобы форма была динамичной. Если изменить эту строку:

dynamic form = uiWrapper.GetForm(); 

Все работает :)

На вершине, что logic.Save (form.ToDomainClass()) также идет непосредственно на Save (DomainTypeOfForm), а не Save (BaseDomainForm) поэтому я также могу избежать головной боли. Я знал, что как только я придумаю проблему, я смогу применить ответ и в своем классе логики.

+0

1) Является ли плохая форма отмечать мой собственный ответ в качестве решения? 2) Эрик, если вы используете C# 4.0, я надеюсь, что это решение работает и для вашей проблемы. – ARM

+0

Отметьте это как ответ, я полностью забыл о динамике, потому что я только начал работу, где мы все еще используем 3.5! –

0

Я пытался сделать что-то похожее на Linq, я пытался создать класс, который наследует некоторые стандартные поля (ID и т. Д.). Я обнаружил, что механизм Linq по умолчанию будет использовать только поля из созданного класса, а не из унаследованных классов или интерфейсов.

Для построения Type просто использовать такой код:

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

var form = Activator.CreateInstance (uiWrapper.GetForm(). GetType()); предоставляет мне форму, но, к сожалению, она помещается в качестве объекта в этой точке и форме. Validate (this.ModelState) больше не является действительным вызовом метода. Спасибо за попытку. – ARM