2010-08-25 3 views
25

J'ai un service WCF qui vit côte à côte avec un site web MVC2. Je voudrais que mon URL pour le service à ressembler à ceci:Routage MVC2 avec WCF ServiceRoute: Html.ActionLink rendant les liens incorrects!

http://localhost/projdir/Service

Le site MVC est à ses débuts il a encore tous ses contrôleurs etc. boilerplate

Le code suivant fonctionne à premier coup d'oeil dans 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 
    ); 
} 

Le service apparaît juste où je l'ai décrit et fonctionne comme annoncé. Génial.

Cependant, je viens de remarquer que commander mon code de cette façon change tous mes ActionLink. Par exemple, l'onglet "À propos" sur le site MVC apparaît maintenant comme ceci:

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

Ceci est évidemment incorrect (il devrait être http://localhost/projdir/Home/About/).

Si je déplace l'ajout ServiceRoute sous l'appel par défaut MapRoute(), une erreur de contrôleur est manquante. (En fait, je reçois une erreur "StructureMapControllerFactory n'a pas retourné une instance d'un contrôleur", parce que je suis câblé avec StructureMap, duh, ce n'est pas un contrôleur pour commencer.)

Fait intéressant, cela ne semble affecter la sortie de Html.ActionLink(). Je peux taper manuellement http://localhost/projdir/Home/About/ et arriver à la bonne page.

Quelle erreur de débutant horriblement évidente je fais?

+0

Peut-être lié? http://stackoverflow.com/questions/1470997/html-actionlink-construct-wrong-link-when-a-non-mvc-route-is-added – roufamatic

Répondre

18

Essayez de déplacer l'itinéraire de service après l'itinéraire MVC. Mais pour éviter l'erreur "contrôleur manquant" que vous avez eu avant, ajoutez l'itinéraire MVC avec un Route Constraint. Ces contraintes d'itinéraire peuvent être Regex - en principe, vous voudriez que votre contrainte d'itinéraire soit n'importe quel contrôleur qui est et non "Service". Lorsqu'une demande de "Service" est demandée, elle le fera tomber et sa route de service de la WCF.

+2

Merci! J'ai utilisé 'new {controller ="^{?! Service} "}' comme contrainte et cela a fonctionné comme un charme. Comprenez-vous pourquoi la route de service ne peut pas être avant la route MVC? – roufamatic

+0

Les jetons {controller} et {action} sont des jetons spéciaux qui sont toujours implicites dans MVC (vous pouvez aussi définir vos propres jetons, mais ceux-ci sont toujours présents).Lorsque vous placez l'itinéraire de service en premier, il ne peut pas trouver ces jetons n'importe où dans le canevas que vous avez défini pour votre itinéraire. Il suffit donc de les ajouter en tant que chaînes de requête. Donc, il devient assez confus lorsque la route de service est en premier. Généralement, vous souhaitez commander vos itinéraires afin que les itinéraires les plus «spécifiques» soient définis en premier. Heureux d'entendre que ça fonctionne pour vous maintenant. –

+5

Merci, c'est utile. Correction pour les futurs googleurs: le modèle que j'ai utilisé était en fait '^ (?! Service). *' – roufamatic

3

Une autre solution est d'hériter du ServiceRoute et remplacer la méthode GetVirtualPath pour revenir null comme décrit 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 cette façon, sélectionnez la cartographie de l'itinéraire inverse jamais cette route pour toute action. Fonctionne comme un charme

8

Je RESOLUE que:

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

J'espère que ce bon pour vous

+0

Excellent - j'ai complètement oublié ces filtres! JE VOUS REMERCIE! –