Почему TryUpdateModel возвращает false, даже если свойства установлены и допустимы? - PullRequest
2 голосов
/ 13 февраля 2012

У меня есть веб-приложение на основе ASP.Net MVC3.Мне нужно представление «Создать», которое не будет знать тип модели, пока пользователь не выберет подтип для создания из раскрывающегося списка.Чтобы попытаться решить эту проблему, я создал шаблон редактора в разделе Shared / EditorTemplates для каждого производного типа модели.Это позволяет мне создать один «Create.cs», который строго типизирован для модели представления.Модель представления имеет только два члена, перечисление и сложный тип.Идея состоит в том, что представление сначала будет отображать только раскрывающийся список (редактор для элемента enum), а затем, когда пользователь первоначально отправляет указанный «тип модели» (выбранное значение), действие POST может проверять «тип модели».msgstr "указан и создан правильный тип производной модели для единственного сложного члена модели представления, тип которого является базовым типом для всех возможных" типов модели ".

Объекты модели абстрактного + производного типа ...

public abstract class MyModelBase
{
    public MyModelType_e ModelType {get; set; }
    [Required]
    public string Name { get; set; }
}

public class DerivedType1 : MyModelBase
{ ... }

public class DerivedType2 : MyModelBase
{ ... }

public class DerivedType3 : MyModelBase
{ ... }

У меня есть модель сложного представления следующим образом ...

public enum MyModelType_e
{
    DerivedType1 = 0,
    DerivedType2 = 1,
    DerivedType3 = 2
}

public class MyModelCreate
{
    public MyModelType_e ModelTypeForSelectList { get; set; }
    public MyModelBase ModelBase { get; set; }
}

Создание экземпляра действия моего контроллера GETвышеупомянутая модель представления для представления, т.е. только раскрывающийся список, отображаемый с элементами на основе перечисления MyModelType_e + значение свойства ModelBase модели, изначально равно нулю.Таким образом, метод действия GET выглядит следующим образом ...

[HttpGet]
public ActionResult Create()
{
    return View(new MyModelCreate());
}

Обратите внимание на комментарий в шапке ниже относительно сути моей проблемы, которая заключается в том, что TryUpdateModel завершается неудачно (см. Ниже), даже если он устанавливает свойства ModelBase.(производный тип) член к соответствующим значениям формы, как и ожидалось ...

[HttpPost]
public ActionResult Create(MyModelCreate model)
{
    if (model.ModelBase == null || 
        (int)model.ModelTypeForSelectList != model.ModelBase.ModelType)
    {
        switch (model.ModelType)
        {
            case MyModelType_e.DerivedType1:
                model.ModelBase = new DerivedType1();
                break;
            case MyModelType_e.DerivedType2:
                model.ModelBase = new DerivedType2();
                break;
            case MyModelType_e.DerivedType3:
                model.ModelBase = new DerivedType3();
                break;
        }
        return View(model);
    }

    if (!TryUpdateModel(model.ModelBase))
        return View(model); // <<< THIS HAPPENS EVEN THOUGH ModelBase APPEARS TO BE UPDATED PROPERLY... 
    // For instance, I can see right here with intellisense that model.ModelBase.Name
    // is NOT null or empty but rather is truly updated with the correct form value(s)...

    // TODO: Insert the record, etc... (currently we never get here...)
}

Таким образом, в приведенном выше разделе проистекает проблема, но вот мое мнение, чтобы помочь понять ...

 @model MyNamespace.MyModelCreate

 <h2>Create</h2>

 ...

 @using (Html.BeginForm())
 {
     @Html.ValidationSummary(false)
    <fieldset>
    <legend>Input</legend>
    <div class="editor-label">
    @Html.Label("Select Model Type")
    </div>
    <div>
    @Html.EnumDropDownListFor(model => model.ModelType)
    @Html.ValidationMessageFor(model => model.ModelType)
    </div>

    @* 
    Conditionally show the correct editor template... 
    There is one existing under ../Shared/EditorTemplates for each
    derived type (DerivedType1, DerivedType2, DerivedType3, etc...)
    This much is working in the sense that the correct editor fields
    are displayed based on what the user selects in the above drop-down.
    *@
    @if (Model.InputModel != null)
    {  
        @Html.EditorFor(model => model.ModelBase);
    }

    <p>
        <input type="submit" value="Continue" />
    </p>              
    </fieldset>
}

Таким образом, однажды с начальным POST (выбран тип модели), мой метод действия POST проваливается в строку TryUpdateModel, но по какой-то причине проверка завершается неудачно.Часть, которую я действительно не понимаю, состоит в том, что сводка проверки сообщает «Требуется имя», хотя я могу четко наблюдать, как TryUpdateModel правильно устанавливает правильное Имя на элементе ModelBase модели представления.

Я бы очень хотелценим любую помощь или руководство здесь ... Я довольно новичок в ASP.NET MVC, и я открыт для того, чтобы делать вещи по-другому, так как я понимаю, что, возможно, есть другие способы, которыми я мог бы разработать свои запросы / действия + представления для выполнения этого "многоэтапного"«проблема, но я на самом деле собираюсь сделать простейшую возможную вещь, поэтому мне нравится подход EditorTemplate для обработки производных типов моделей и т. д.

Заранее спасибо ...

Ответы [ 2 ]

3 голосов
/ 04 июля 2016

Чек ModelState. После запуска TryUpdateModel должны быть ошибки. Мне пришлось удалить атрибут Required из некоторых свойств.

0 голосов
/ 19 марта 2012

Мое решение в основном заключалось в расширении двух дополнительных действий контроллера (GET и POST). Я создал отдельные представления в ../Shared/EditorTemplates, которые строго типизированы (по одному для каждого производного типа модели). Таким образом, исходное действие «Создать» POST получает только выбранный тип (модель - это просто значение enum, указывающее желаемый тип), а затем перенаправляет на другое действие контроллера, такое как «CreateByType», которое получает новый экземпляр запрошенного конкретного типа и возвращает правильный вид редактирования. Дополнительные действия контроллера «CreateByType» (GET и POST) должны иметь дело только с абстрактной базой, потому что он запрашивает экземпляр из сервисного уровня (передавая значение перечисления). Затем все, что мне нужно было сделать, это создать представление под EditorTemplates для каждого конкретного типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...