¿Cómo puedo reconstruir la URL / ruta en ASP.NET MVC a partir de los datos guardados?
-
05-07-2019 - |
Pregunta
Mi falta de familiaridad con el marco de ASP.NET MVC y la plomería del mismo me ha traído hasta aquí, y aprecio la paciencia que tomará para que cualquiera lea y considere mi pregunta.
Bueno, aquí está el escenario: tengo una aplicación que tiene numerosas páginas con cuadrículas que muestran datos basados ??en búsquedas, desglosando de otros datos, informes basados ??en datos específicos del contexto (es decir, están en una página de detalles para Foo , luego haga clic en un enlace que muestra una tabla de datos relacionados con Foo), etc.
Desde cualquiera y todas estas páginas, que están en toda la aplicación, el usuario puede guardar el informe " " o rejilla, dándole un nombre y una descripción. Esto realmente no guarda los datos, mostrados en la cuadrícula, sino que guarda los parámetros que definen cómo se ve la cuadrícula, guarda los parámetros que se usaron para obtener los datos y guarda los parámetros que definen " donde " en la aplicación son (la acción, el controlador, la ruta), básicamente un conjunto de metadatos sobre el informe / cuadrícula y cómo construirlo.
Todos estos informes guardados están disponibles en una sola lista, mostrando el nombre y la descripción, en una página determinada de la aplicación, con cada enlace a una URL genérica, como " / Reports / Saved / 248 " (donde 248 es un ejemplo de ID del informe).
Aquí está la parte en la que necesito ayuda:
Cuando llego a la acción a través de la URL " / Informes / Guardado / 248 " y saque los metadatos de la base de datos para ese informe en particular, ¿cómo puedo redirigir los datos y la solicitud a la misma acción, controlador y ruta utilizada para mostrar la vista desde la que se guardó originalmente el informe? Básicamente, quiero que el usuario vea el informe en la misma vista, con la misma URL desde la que se guardó. Si es posible, sería bueno para mí poder, básicamente, " llamar " esa misma acción como si estuviera haciendo una llamada de método.
ACTUALIZACIÓN: desafortunadamente, nuestras páginas de informes (es decir, las páginas en las que aparecen estas cuadrículas) NO están usando URL RESTful. Por ejemplo, tenemos lo que llamamos una página de Búsqueda avanzada, que requiere un número bastante grande de parámetros potenciales (casi 30 ) que provienen de un formulario que contiene listas de selección, cuadros de texto, etc. Cuando el usuario envía esa página, realizamos un POST a una acción que acepta un tipo complejo que el archivador de modelos crea para nosotros; esa misma acción es lo que quiero llamar cuando el usuario selecciona una búsqueda avanzada guardada de la base de datos. Ese ejemplo resume mi problema.
Gracias
Solución
Creo que querrá usar RedirectToAction con la firma que toma un RouteValueDictionary. El método al que está redirigiendo tendrá que poder extraer los valores del ValueProvider en el controlador. Puede parecer algo como:
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;
}
EDIT
El uso de un modelo de filtro como parámetro para su método puede hacerlo más fácil. Solo necesitas las versiones GET y POST de tu acción.
[ActionName("People")]
[AcceptVerbs( HttpVerbs.Get )]
public ActionResult PeopleDisplay( SearchModel filter )
{
return People( filter );
}
[AcceptVerbs( HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult People( SearchModel filter )
{
....
}
Luego, almacenaría en su base de datos para el informe los parámetros del filtro (por nombre), la Acción (" Gente ") y el Controlador. El resultado de la redirección usará GET y se dirigirá al método PeopleDisplay, que a su vez simplemente llama al método People con el parámetro correcto. La publicación desde el formulario llama directamente al método People. El uso de dos métodos le permite utilizar el mecanismo de prevención CSRF. Es posible que pueda usar un indicador en TempData para asegurarse de que la acción GET solo se invoque a través del mecanismo de redireccionamiento si desea restringir el acceso a él.
EDITAR FINAL
Otra alternativa, sería simplemente almacenar la Vista utilizada también y, en lugar de hacer una redirección, simplemente renderizar la vista apropiada. Una de las cosas que querrá tener en cuenta es que al realizar la redirección se obtendrá una URL que contiene todos los parámetros, mientras que la visualización dejará solo la URL y solo mostrará la misma vista que la URL utilizada al crear el informe. .
Otros consejos
Puede usar el método RedirectToAction para emitir un redireccionamiento 301 a un método de acción específico en cualquier controlador, junto con los valores de ruta:
ReportMeta meta = _reportDataAccess.Get(id);
return RedirectToAction(meta.Action, meta.Controller, meta.RouteData);
donde esos valores son algo como:
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
};
Por supuesto, el problema inmediato que puedo ver con esto es lo que sucede cuando su controlador / métodos de acción cambian con el tiempo, los datos del informe no serán válidos. Pero probablemente ya hayas pensado en eso.