Как передать данные ViewModel между запросами POST в ASP.NET MVC? - PullRequest
3 голосов
/ 16 ноября 2010

У меня есть ViewModel, например, так:

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
    }
}

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

Ответы [ 3 ]

2 голосов
/ 16 ноября 2010

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

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

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

2 голосов
/ 16 ноября 2010

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

[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");
}

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

0 голосов
/ 16 ноября 2010

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

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

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

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

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

...