2010-08-25 21 views
25

Tengo un servicio WCF que vive en paralelo con un sitio web de MVC2. Me gustaría que mi URL para el servicio a tener este aspecto:Enrutamiento MVC2 con WCF ServiceRoute: Html.ActionLink representa enlaces incorrectos!

http://localhost/projdir/Service

El sitio MVC está en su infancia por lo que todavía tiene todos sus controladores de caldera etc.

El código siguiente funciona en primer vistazo en global.asax:

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

    routes.Add(new ServiceRoute("Service", new ServiceHostFactory(), 
       typeof(MyService))); 

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

El servicio aparece justo donde lo describí y funciona como se anuncia. Estupendo.

Sin embargo, acabo de notar que ordenar mi código de esta manera cambia todos mis ActionLink. Por ejemplo, la pestaña "Acerca de" en el sitio MVC ahora aparece como esto:

http://localhost/projdir/Service?action=About&controller=Home

Esto es obviamente incorrecto (debe ser http://localhost/projdir/Home/About/).

Si muevo la adición ServiceRoute debajo de la llamada predeterminada MapRoute(), entonces me sale un error de controlador faltante. (En realidad me sale un "StructureMapControllerFactory no arrojó una instancia de un controlador de" error, porque estoy conecté con StructureMap, duh, que no es un controlador para empezar.)

Curiosamente, sólo parece estar afectando la salida de Html.ActionLink(). Puedo escribir manualmente en http://localhost/projdir/Home/About/ y llegar a la página correcta.

¿Qué error tan obvio de principiante estoy cometiendo?

+0

Posiblemente relacionado? http://stackoverflow.com/questions/1470997/html-actionlink-construct-wrong-link-when-a-non-mvc-route-is-added – roufamatic

Respuesta

18

Intente mover la ruta del servicio después de la ruta MVC. Pero para evitar el error de "controlador faltante" que obtuvo antes, agregue la ruta MVC con a Route Constraint. Estas restricciones de ruta pueden ser Regex; básicamente, desearía que su restricción de ruta sea cualquier controlador que sea y no "Servicio". Cuando se solicita una solicitud de "Servicio", la hará pasar por su ruta de servicio WCF.

+2

¡Gracias! Usé 'new {controller ="^{?! Service} "}' como la restricción y funcionó como un amuleto. ¿Comprende por qué la ruta del servicio no puede estar antes de la ruta MVC? – roufamatic

+0

Los tokens {controlador} y {acción} son tokens especiales que están implícitos en MVC siempre (también puedes definir tus propios tokens, pero estos son * siempre * allí).Cuando coloca la ruta de servicio primero, no puede encontrar esos tokens en ningún lugar del patrón que haya definido para su ruta, por lo que solo los agrega como cadenas de consulta. Por lo tanto, se está confundiendo bastante cuando la ruta de servicio es la primera. Por lo general, desea ordenar sus rutas para que las rutas más "específicas" se definan primero. Me alegra saber que está trabajando para ti ahora. –

+5

Gracias, eso es útil. Corrección para futuros googlers: el patrón que utilicé fue en realidad '^ (?! Service). *' – roufamatic

3

Otra solución es heredar la ServiceRoute y reemplazar el método GetVirtualPath para volver null como se describe here

public class AppServiceRoute : ServiceRoute 
{ 
    public AppServiceRoute(string routePrefix, ServiceHostFactoryBase serviceHostFactory, Type serviceType) 
     : base(routePrefix, serviceHostFactory, serviceType) 
    { 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     return null; 
    } 
} 

De esta manera, revertir mapeo ruta nunca se seleccione esta ruta para cualquier acción. Funciona como un encanto

8

resolví con eso:

 routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
      new { controller = "^(?!api).*" } 
     ); 
     routes.Add(new ServiceRoute("api", new DataServiceHostFactory(), typeof(dwService))); 

espero que este bien para usted

+0

Excelente: ¡Me olvidé completamente de esos filtros! ¡GRACIAS! –

Cuestiones relacionadas