Как я могу восстановить URL / маршрут в ASP.NET MVC из сохраненных данных?

StackOverflow https://stackoverflow.com/questions/825616

Вопрос

Мое незнание фреймворка ASP.NET MVC и его структуры привело меня сюда, и я ценю терпение, которое потребуется любому, чтобы прочитать и рассмотреть мой вопрос!

Итак, вот сценарий:У меня есть приложение, в котором есть множество страниц с сетками, которые отображают данные на основе поиска, детализации по другим данным, отчеты на основе контекстно-зависимых данных (т.Е.они находятся на странице сведений о Foo, затем нажмите на ссылку, которая показывает таблицу данных, связанных с Foo) и т.д.

С любой из этих страниц, которые есть по всему приложению, пользователь может сохранить "отчет" или таблицу, присвоив ему имя и описание.Это на самом деле не столько сохраняет данные, отображаемые в таблице, сколько сохраняет параметры, которые определяют, как выглядит сетка, сохраняет параметры, которые использовались для получить данные и сохраняет параметры, которые определяют, "где" в приложении они находятся (действие, контроллер, маршрут) - в основном набор метаданных об отчете / сетке и о том, как ее построить.

Все эти сохраненные отчеты доступны в виде единого списка с отображением названия и описания на определенной странице приложения, причем каждый из них ссылается на общий URL-адрес, например "/ Reports /Saved /248" (где 248 - пример идентификатора отчета).

Вот та часть, в которой мне нужна помощь:

Когда я перейду к действию по URL-адресу "/ Reports / Saved / 248" и извлеку метаданные из базы данных для этого конкретного отчета, как я могу перенаправить эти данные и запрос на то же действие, контроллер и маршрут, которые использовались для отображения представления, из которого отчет был первоначально сохранен?По сути, я хочу, чтобы пользователь просматривал отчет в том же виде, с тем же URL-адресом, с которого он был сохранен.Если возможно, было бы неплохо, чтобы я мог в принципе "вызывать" то же самое действие, как если бы я выполнял вызов метода.


Обновить:К сожалению, наши страницы отчетов (т.е.страницы, на которых отображаются эти сетки), НЕ используют RESTful URL-адреса - например, у нас есть то, что мы называем страницей расширенного поиска, которая принимает довольно большое количество потенциальных параметров (почти 30), поступающих из формы, содержащей списки выбора, текстовые поля и т.д.Когда пользователь отправляет эту страницу, мы выполняем публикацию для действия, которое принимает сложный тип, который создает для нас model binder - это то же самое действие, которое я хочу вызвать, когда пользователь выбирает сохраненный Расширенный поиск из базы данных.Этот пример олицетворяет мою проблему.

Спасибо

Это было полезно?

Решение

Я думаю, что вы захотите использовать RedirectToAction с подписью, которая принимает RouteValueDictionary.Метод, на который вы перенаправляете, должен иметь возможность извлекать значения из ValueProvider на контроллере.Это может выглядеть примерно так:

public ActionResult Saved( int id )
{
    var reportParams = db.Reports.SingleOrDefault( r => r.ID == id );
    if (reportParams == null)
       ...handle error...

    var routeValues = ParamsToRouteValueDictionary( reportParams );

    return RedirectToAction( reportParams.Action, reportParams.Controller, routeValues );
}

private RouteValueDictionary ParamsToRouteValueDictionary( object parameters )
{
     var values = new RouteValueDictionary();
     var properties = parameters.GetType().GetProperties()
                                .Where( p => p.Name != "Action" && p.Name != "Controller" );
     foreach (var prop in properties)
     {
         values.Add( prop.Name, prop.GetValue(parameters,null) );
     }

     return values;
}

Редактировать

Использование модели фильтра в качестве параметра для вашего метода на самом деле может упростить задачу.Вам просто нужно ПОЛУЧИТЬ и ОПУБЛИКОВАТЬ версии вашего действия.

 [ActionName("People")]
 [AcceptVerbs( HttpVerbs.Get )]
 public ActionResult PeopleDisplay( SearchModel filter )
 {
     return People( filter );
 }

 [AcceptVerbs( HttpVerbs.Post)]
 [ValidateAntiForgeryToken]
 public ActionResult People( SearchModel filter )
 {
     ....
 }

Затем вы сохранили бы в своей базе данных для отчета параметры фильтра (по имени), Действие ("Люди") и контроллер.Результат перенаправления будет использовать GET и будет направлен методу PeopleDisplay, который, в свою очередь, просто вызывает метод People с правильным параметром.Публикация из формы напрямую вызывает метод People.Использование двух методов позволяет использовать механизм предотвращения CSRF.Возможно, вы сможете использовать флаг в TempData, чтобы гарантировать, что действие GET вызывается только через механизм перенаправления, если вы хотите ограничить доступ к нему.

ОКОНЧАТЕЛЬНАЯ ПРАВКА

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

Другие советы

Вы можете использовать метод RedirectToAction для выдачи перенаправления 301 на определенный метод действия на любом контроллере вместе со значениями маршрута:

ReportMeta meta = _reportDataAccess.Get(id);
return RedirectToAction(meta.Action, meta.Controller, meta.RouteData);

где эти значения что-то вроде:

meta.Action = "Bar";
meta.Controller = "Foo";
meta.RouteData = new {
    // possibly settings for the grid
    start = DateTime.Min,
    end = DateTime.Now,
    sort = "Date"
    // you get the idea
};

Конечно, непосредственная проблема, с которой я могу столкнуться, это то, что происходит, когда ваш контроллер / методы действий со временем меняются, данные отчета будут недействительными. Но тогда вы, наверное, уже подумали об этом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top