MVC-передача данных с RedirectToAction()

Я хотел бы взять данные, введенные в пользовательскую форму MVC, и отобразить их в другом представлении.

класс имеет следующую закрытую переменную:

IList<string> _pagecontent = new List<string>();

следующее действие принимает объект FormCollection, проверяет его и передает в представление "предварительный просмотр"в виде списка:

[Authorize(Roles = "Admins")]
[ValidateInput(false)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateContent(FormCollection collection)
{
    if (ModelState.IsValid)
    {
        string PageToInsert = collection["PageToInsert"];
        string PageHeader = collection["PageHeader"];
        string PageBody = collection["PageBody"];

        //validate, excluded...

        _pagecontent.Add(PageToInsert);
        _pagecontent.Add(PageHeader);
        _pagecontent.Add(PageBody);

    }
    return RedirectToAction("Preview", _pagecontent);
}

представление предварительного просмотра имеет следующую директиву страницы для передачи строго типизированного списка объектов:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Template.Master" Inherits="System.Web.Mvc.ViewPage<List<string>>" %>

Я ожидал бы, что смогу использовать модель возражаю против получения моих данных, но, увы, не могу. На следующей строке я получаю error index out of bounds исключение, указывающее, что индекс должен быть неотрицательным и меньше размера коллекции:

<% if (Model[0].ToString() == "0") { %>

и некоторые странные параметры были добавлены к URL-адресу, поскольку он разрешает http://localhost:1894/Admin/Preview?Capacity=4&Count=3

Итак, у меня есть два вопроса:

  1. когда я вызываю RedirectToAction и передаю ему свой список, почему он недоступен в объекте модели представления?
  2. Как правильно способ сделать то, что я пытаюсь сделать, а именно передать коллекцию строк в представление для отображения там?

8 ответов


попробуйте использовать данных tempdata. Это как одноразовый объект сеанса. Вы помещаете нужные значения в TempData, немедленно перенаправляете и получаете их. Здесь есть хорошая запись:http://blogs.teamb.com/craigstuntz/2009/01/23/37947/


будьте осторожны при использовании TempData. Он отлично работает в среде с одним сервером, но в облачной среде он может работать не так, как ожидалось, поскольку вы не можете гарантировать, что запрос попадет на ту же машину. Это происходит потому, что TempData полагаются на asp.net сеанс. Но если вы используете другой менеджер сеансов, такой как SQL или AppFabric Cache, он будет работать нормально.


второй параметр RedirectAction-routeValues, а не model.

protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues);

попробуйте использовать TempData для модели. Его для сохранения данных между перенаправлениями.


проблема с RedirectToAction заключается в том, что он возвращает HTTP 302, а браузер затем самостоятельно выполняет новый HTTP-запрос. Возможно, вы захотите использовать cookie и/или объект сеанса для сохранения данных между запросами.


это не работает, потому что RedirectToAction фактически отправляет обратно Http 302 в браузер. Когда браузер получает этот 302, он делает новый запрос на сервер, запрашивающий новую страницу. Новый запрос, новые временные переменные.

вы также столкнетесь с этой проблемой при попытке сохранить/отредактировать / удалить что-то, и по какой-то причине вы отрицаете это, и вам нужно снова вернуть старую форму.

, вместо:

return RedirectToAction("Preview", _pagecontent);

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

return PreviewLogic(_pagecontent);

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


похоже, вы пытаетесь сделать:

public ActionResult UpdateContent(FormCollection form) {
    ...
    return View("Preview", _pagecontent);
}

обратите внимание, что перенаправление должно быть "чистым листом" для браузера (за исключением таких вещей, как файл cookie auth). Вы не можете сказать браузеру передать информацию следующему запросу, так как следующий запрос должен быть в состоянии стоять сам по себе. Все, что вам нужно сделать, это сказать браузеру, какой URL запросить дальше. В ASP.NET MVC, когда вы передаете аргумент-объект в RedirectToAction, общедоступными свойствами этого объекта являются добавляется в качестве параметров строки запроса к сгенерированному URL-адресу.


не можете ли вы просто сделать 2 результата действия с тем же именем и отметить 1 из них с помощью HttpPost?

    public ActionResult UpdateContent(FormCollection preview = null)
    {
        return View(preview);
    }
    [HttpPost]
    public ActionResult UpdateContent(FormCollection collection = null, bool preview = false)
    {
        if (preview)
            return UpdateContent(collection);
        else
            return UpdateContent(null);
    }

похоже, вы ищете команду UpdateModel:

Проверьте сообщение в блоге ScottGu по теме:

улучшенные методы UpdateModel и TryUpdateModel