2010-08-25 5 views
25

Ho un servizio WCF che vive in parallelo con un sito Web MVC2. Mi piacerebbe per il mio URL per il servizio a guardare come questo:Routing MVC2 con servizio WCFRoute: Html.ActionLink che mostra collegamenti errati!

http://localhost/projdir/Service

Il sito MVC è nella sua infanzia quindi ha ancora tutti i suoi controllori boilerplate ecc

Il seguente codice funziona a primo sguardo su 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 
    ); 
} 

Il servizio appare proprio dove ho descritto e funziona come pubblicizzato. Grande.

Tuttavia, ho appena notato che l'ordine del mio codice in questo modo cambia tutti i miei ActionLink. Ad esempio, la scheda "Informazioni" sul sito MVC ora appare così:

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

Questo è ovviamente corretta (dovrebbe essere http://localhost/projdir/Home/About/).

Se si sposta l'aggiunta ServiceRoute al di sotto della chiamata predefinita MapRoute(), viene visualizzato un errore del controller mancante. (In realtà ottengo un errore "StructureMapControllerFactory non restituisce un'istanza di un controller", perché sono cablato con StructureMap, duh, non è un controller per cominciare.)

È interessante notare che sembra solo influenzare l'output di Html.ActionLink(). Posso digitare manualmente http://localhost/projdir/Home/About/ e arrivare alla pagina corretta.

Quale errore newbie orribilmente ovvio sto facendo?

+0

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

risposta

18

Provare a spostare il percorso di servizio dopo il il percorso MVC. Ma per evitare l'errore "controller mancante" che hai ottenuto prima, aggiungi la route MVC con a Route Constraint. Questi vincoli di percorso possono essere Regex, in pratica si desidera che il vincolo del percorso sia qualsiasi controller che sia non "Servizio". Quando viene richiesta una richiesta di "Servizio", la farà cadere e il suo percorso di servizio WCF.

+2

Grazie! Ho usato 'new {controller ="^{?! Service} "}' come vincolo e ha funzionato come un incantesimo. Capisci perché il percorso di servizio non può essere prima della rotta MVC? – roufamatic

+0

I token {controller} e {action} sono token speciali impliciti in MVC sempre (puoi anche definire i token personali ma questi sono * sempre * lì).Quando inserisci per primo il percorso del servizio, non riesce a trovare quei token in nessun punto del pattern che hai definito per il tuo percorso, quindi li aggiunge come stringhe di query. Quindi diventa piuttosto confuso quando il percorso del servizio è il primo. In genere si desidera ordinare i percorsi in modo che vengano definiti prima i percorsi più "specifici". Sono contento di sapere che sta funzionando per te ora. –

+5

Grazie, è utile. Correzione per i futuri googler: il pattern che ho usato era in realtà '^ (?! Service). *' – roufamatic

3

Un'altra soluzione è quella di ereditare il ServiceRoute e l'override del metodo GetVirtualPath per tornare null come descritto 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; 
    } 
} 

In questo modo, invertire la mappatura percorso mai scegliere questo percorso per qualsiasi azione. Funziona come un fascino

8

ho deciso con che:

 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))); 

Spero che questo bene per voi

+0

Eccellente - Mi sono completamente dimenticato di questi filtri! GRAZIE! –