2012-03-01 16 views
6

Estoy creando una aplicación web de informes simple para representar informes utilizando ASP.NET MVC3 + WebForms. Los informes mismos son renderizados por el control ReportViewer ASP.NET WebForms, pero me gustaría utilizar ASP.NET MVC para crear la entrada de parámetros.ASP.NET MVC + WebForms - Conflicto de ruta

Me gustaría que todas las solicitudes sigan el esquema de enrutamiento predeterminado de '~/{controller}/{action}/{parameters}', excepto las solicitudes de ~/Report, que deberían ir al informe de representación de WebForm. ¿Cuál es la forma correcta de hacer esto?

Ampliando un poco ..

Tengo dos rutas en Global.asax.cs - el defecto uno y uno para la página Web Forms.

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapRoute(
     "Default", // Route name 
     "{controller}/{action}/{id}", // URL with parameters 
     new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
    ); 

    routes.MapPageRoute("report-rendering", "Report", "~/Render.aspx"); 
} 

Las URL conseguir rindió bien, pero el problema con esto es que cuando entra la petición, la primera ruta también se alimenta de las direcciones URL de la segunda, es decir ~/Report?id=7 intenta llamar al método Index en el ReportController (que no existe).

Si lo cambio por lo que el 'Informe de representación' ruta está antes que la ruta 'Default', así:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapPageRoute("report-rendering", "Report", "~/Render.aspx"); 

    routes.MapRoute(
     "Default", // Route name 
     "{controller}/{action}/{id}", // URL with parameters 
     new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
    ); 
} 

ahora llama a la Html.ActionLink() hacer que los errores de navegación, es decir

`@Html.ActionLink("Report list", "Index", "ReportList")` 

Renders

`http://localhost:49910/Report?action=Index&controller=ReportList` 

Mi solución actual pone la ruta 'Default' en primer lugar, mientras que la adición una restricción de expresiones regulares para ignorar las solicitudes de controlador de la 'Informe', así:

routes.MapRoute(
    "Default", // Route name 
    "{controller}/{action}/{id}", // URL with parameters 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults 
    new { controller = @"(?!report$).*" } 
); 

Esto no se siente limpio. De nuevo, ¿cuál es la forma correcta de hacer esto?

Además, aún no he decidido cómo pasaré los parámetros al formulario de representación: podría usar ambos parámetros de consulta o POSTARlos. Supongo que los parámetros de consulta son más flexibles. ¿Cuál es la mejor práctica aquí?

EDIT:

Durante la investigación de la respuesta por @LeftyX, parece como si hubiera encontrado una respuesta. Para citar a P. Haack de su capítulo de enrutamiento en los Professional ASP.NET MVC 3 (rutas con nombre, capítulo 9, página 233):

... Utilizar nombres para todas sus rutas y utilice siempre el nombre de la ruta al generar direcciones URL . La mayoría de las veces, dejar que enrutamiento resuelva qué ruta que desea utilizar para generar una URL realmente la deja al azar, que no es algo que le sienta bien al desarrollador obsesivo-compulsivo de control freak. Al generar una URL, por lo general, sabe exactamente qué ruta desea vincular, por lo que también puede especificarla por su nombre.

La sección mencionada discute una situación muy similar a la que describí.

Pero dado que Html.ActionLink() no tiene una sobrecarga con el parámetro de nombre de ruta, ¿significa esto que no puedo usarlo confiablemente en ninguna parte de la aplicación si tengo una ruta como esta?

Respuesta

1

Esta es la mejor solución que he descubierto.
Me he registrado mi ruta con MapPageRoute (He puesto mi página de informe en una carpeta denominada Informes)

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapPageRoute(
      "report-rendering", 
      "Report/{id}", 
      "~/Reports/Report.aspx" 
     ); 

     routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
      ); 
} 

He creado mi enlace utilizando RouteLink para que pueda especificar la ruta a utilizar:

@Html.RouteLink("Report list", "report-rendering", new { id = 7 }) 

y puedo conseguir la Identificación en mi página de formulario Web como esto:

protected void Page_Load(object sender, EventArgs e) 
{ 
    var id = Page.RouteData.Values["id"] as string; 
} 

Espero que ayude.

ACTUALIZACIÓN:

He creado un método de extensión para hacer su vida más fácil:

public static class ExtensionMethods 
{ 
    public static MvcHtmlString WebFormActionLink(this HtmlHelper htmlHelper, string linkText, string ruoteName, object routeValues) 
    { 
     var helper = new UrlHelper(htmlHelper.ViewContext.RequestContext); 

     var anchor = new TagBuilder("a"); 
     anchor.Attributes["href"] = helper.RouteUrl(routeName, routeValues); 
     anchor.SetInnerText(linkText); 
     return MvcHtmlString.Create(anchor.ToString()); 
    } 
} 

La mejor habría sido utilizar ActionLink en lugar de WebFormActionLink pero tengo problemas con las firmas y no soy un experto en esto.

+0

Gracias por la respuesta. Veo lo que hiciste alli. Como ha agregado el parámetro {id}, las llamadas .RouteLink() sin proporcionar un valor para {id} ya no coinciden con la ruta. Sin embargo, generar una ruta mientras se especifica el parámetro id coincidirá con esta ruta. Esto: @ Html.ActionLink ("Página 1", "Página", "Casa", nuevo {id = 1}, nulo) Generará esto: http: // localhost: 49910/Report/1? Action = Página y controlador = Inicio ¿Cuál no es lo que esperarías, verdad? –

+0

@ghostskunks: Lo sé. Me temo que tiene que usar RouteLink para generar sus enlaces para WebForms o puede intentar extender ActionLink. – LeftyX

+0

@ghostskunks: He tratado de armar algo (respuesta actualizada) pero, como dije, no soy un experto. Es solo una idea – LeftyX

Cuestiones relacionadas