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

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top