ASP.net MVC — как сохранить модель в различных представлениях

Ситуация: в некоторых программах управления проектами, написанных на asp.net, у меня есть страница создания проекта (работает нормально). Мне нужно добавить к этому возможность добавлять задачи из списка шаблонов в предварительное создание этого проекта, НО список доступных задач зависит от некоторых значений, находящихся в форме создания.

Мое абстрактное решение таково:

  • У меня есть представление «Создать» и представление «Добавить задачи» - оба строго типизированы для составной модели представления, определенной в контроллере.
  • Мой метод Create проверяет, какая кнопка использовалась для его вызова — если кнопка была «Добавить задачи», она затем отображает представление AddTasks, передавая модель из представления создания, снова все в том же контроллере.
  • Представление AddTasks публикуется в представлении Create с помощью одной из двух кнопок, одна из которых загружает представление, а другая вызывает фактическое сохранение БД.

Моя проблема заключается в следующем:

  • Разные представления используют разные свойства одной и той же модели, но при передаче этой модели между ними данные сбрасываются (в любом случае перезагружаются или сохраняются).
  • Я предполагаю, что это происходит из-за автоматической привязки данных, хотя я думал, что поля, отсутствующие в форме, не будут перезаписывать существующие данные модели, переданные вниз.
  • В настоящее время в контроллере практически нет кода, управляющего моделью — в этих случаях он передается только из представления в представление.

Это код контроллера:

    // POST: /Project/Create/<viewModel>
    [Authorize, AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind(Exclude = "Id,id")] ProjectViewModel model)
    {
        if (model.SubmitValue == "Create")
        {
            try
            {
                model.Project.Id = Guid.NewGuid();
                model.Save(this.User.Identity.Name);
                return this.RedirectToAction("Details", new {id = model.Project.Id});
            }
            catch (Exception e)
            {
                this.ModelState.AddModelError(e.ToString(), e.ToString());
            }
            return View(model);
        }

        if(model.SubmitValue == "AddTasks")
        {
            return this.View("AddTasks",model);
        }

        return this.View(model);

    }


    //POST: /Project/AddTasks/ + model
    [Authorize, AcceptVerbs(HttpVerbs.Post)]
    public ActionResult AddTasks([Bind(Include = SelectedCarrierTasks")]ProjectViewModel model)
    {
        return View(model);
    }

Вопрос: как поддерживать состояние модели в этих представлениях до тех пор, пока она ее не сохранит?

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

Спасибо, Адам Толли.


person Adam Tolley    schedule 05.11.2009    source источник


Ответы (4)


В данный момент я не могу комментировать вопросы других людей, но единственным реальным вариантом является сеанс, если вы хотите сохранить состояние объектов во время веб-запросов, или сериализовать его и поместить в скрытое поле.

Или последний вариант — изменить способ работы ваших страниц, чтобы вы могли сохранять объект после каждого запроса...

Если вы используете nHibernate, вы можете захотеть изучить шаблон «Разговоры», но это в любом случае просто сохраняет сеанс nHibernate в сеансе asp.net...

person Andy Long    schedule 06.11.2009
comment
Я отмечу это как ответ, так как это наиболее полный набор параметров и включает подход NHibernate (хотя на данный момент я застрял с EF1). - person Adam Tolley; 06.11.2009

Одним из простых решений является сохранение объекта ViewModel в переменной Session и привязка представления из этого источника. Это, безусловно, не самое элегантное решение. Другой вариант, и, вероятно, менее элегантный, - сохранить данные этой модели в базе данных с некоторым временным/несохраненным флагом.

person Oleiro    schedule 05.11.2009

Проблема в том, что когда вы отображаете представление добавления задач, вы не предоставляете поля для своего объекта «Проект», поэтому ModelState теряет данные, связанные с проектом, вам нужно будет предоставить эти поля, чтобы убедиться, что вы не потеряете эти данные .

Вам не нужно отображать эти поля, они могут быть скрытыми и сохранят значение. Просто убедитесь, что если вы будете привязываться к модели представления, вам нужно будет правильно назвать эти поля, как это Model.Project.Property.

person jgarcia    schedule 05.11.2009
comment
Поэтому я могу сохранить его, сохранив его на стороне клиента в скрытых полях, есть ли способ не зависеть от хранилища на стороне клиента? Немного странно загружать страницу и браузер такой довольно большой моделью только ради сохранения методов/представлений в одном и том же контроллере. Спасибо за ваш вклад - person Adam Tolley; 05.11.2009

Возможно, я пытаюсь решить не ту проблему (аля Брюс Экель). Я собираюсь попытаться перейти к структуре, которая меньше нуждается в такой нечеткой границе. Я не хочу принимать парадигму REST только для того, чтобы втиснуть ее в приложение с отслеживанием состояния.

Возможно, эти элементы управления принадлежат одной и той же странице, и я могу использовать некоторые возможности JQuery, чтобы поместить панель вкладок для удобства глаз.

Спасибо тем, кто ответил, я нашел каждого полезным и постараюсь не забыть проголосовать за них, как только у меня появится еще несколько представителей.

person Adam Tolley    schedule 06.11.2009