2010-11-16 4 views
3

У меня есть ViewModel как так:Как передать данные ViewModel между запросами POST в ASP.NET MVC?

public class ProductEditModel 
{ 
    public string Name { get; set; } 
    public int CategoryId { get; set; } 
    public SelectList Categories { get; set; } 

    public ProductEditModel() 
    { 
     var categories = Database.GetCategories(); // made-up method 
     Categories = new SelectList(categories, "Key", "Value"); 
    } 
} 

Тогда у меня есть два метода контроллера, который использует эту модель:

public ActionResult Create() 
{ 
    var model = new ProductEditModel(); 
    return View(model); 
} 

[HttpPost] 
public ActionResult Create(ProductEditModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // convert the model to the actual entity 
     var product = Mapper.Map(model, new Product()); 
     Database.Save(product); 
     return View("Success"); 
    } 
    else 
    { 
     return View(model); // this is where it fails 
    } 
} 

Первый раз, когда пользователь переходит к Create мнению, они представлены с список категорий. Однако, если они не подтверждают проверку, представление возвращается к ним, за исключением того, что значение Categories равно null. Это понятно, потому что ModelBinder не сохраняется Categories, если он не был в запросе POST. Мой вопрос: какой лучший способ сохранить Categories? Я могу сделать что-то вроде этого:

[HttpPost] 
public ActionResult Create(ProductEditModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // convert the model to the actual entity 
     var product = Mapper.Map(model, new Product()); 
     Database.Save(product); 
     return View("Success"); 
    } 
    else 
    { 
     // manually populate Categories again if validation failed 
     model.Categories = new SelectList(categories, "Key", "Value"); 
     return View(model); // this is where it fails 
    } 
} 

Но это уродливое решение. Как еще я могу это продолжать? Я не могу использовать скрытое поле, потому что это коллекция.

ответ

2

Обычно я реализую свои списки (для выпадающих списков) как свойство readonly. Когда представление получает значение, свойство самодостаточно для того, что ему нужно, чтобы вернуть значения.

public SelectList Categories 
{ 
    get 
    { 
     var categories = Database.GetCategories(); // made-up method 
     return new SelectList(categories, "Key", "Value"); 
    } 
} 

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

0

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

Как показано в следующем примере:

public IEnumerable<SelectListItem> CountryList 
{ 
    get 
    { 
     return GetCountryList().Select(
      t => new SelectListItem { Text = t.Name, Value = Convert.ToString(t.CountryID) }); 
    } 
} 

GetCountryList() является функцией, задать Singleton данных. Это произойдет только один раз в жизненном цикле приложения.

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

Если вам нужно получить доступ к списку, который время от времени меняется, просто не используйте класс Singleton.

+0

Иными словами, повторно заполнить списки вручную? –

+0

Что вы подразумеваете под рукой? – Lorenzo

+0

О, ооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооаеееееееееееееееее –

2

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

[HttpPost] 
public ActionResult Create(ProductEditModel model) 
{ 
    if (!ModelState.IsValid) 
    { 
     // manually populate Categories again if validation failed 
     model.Categories = Repository.GetCategories(); 
     return View(model); 
    } 

    // convert the model to the actual entity 
    var product = Mapper.Map(model, new Product()); 
    Database.Save(product); 

    // I would recommend you to redirect here 
    return RedirectToAction("Success"); 
} 

Для дальнейшего реорганизовать это я бы порекомендовал вам наблюдать за отличную Putting Your Controllers on a Diet видеообращение Джимми Богард.

+0

Причина, по которой я говорю, что она уродлива, объясняется тем, что она нарушает принцип единой ответственности: ViewModel должен знать, как получить данные, необходимые для отправки в представление. Если вам нужно установить его извне, тогда это просто DTO. –

Смежные вопросы