在ASP.NET MVC 中宿主WCF Rest 服务的问题及解决方法

好久没写博客,今天上来看看,都长草了,看来得打扫打扫了。

最近在研究 ASP.NET MVC 3和WCF Reset Service,突然想看看把它们放在一起会怎么样。想到这里动手就干。下面就是我写的代码:

public class MvcApplication : System.Web.HttpApplication

{

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)

    {

        filters.Add(new HandleErrorAttribute());

    }

 

    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 }

        );

 

    }

 

    protected void Application_Start()

    {

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);

         RouteTable.Routes.Add(new ServiceRoute("Uap"new WebServiceHostFactory(), typeof(Service.UapService)));

       RegisterRoutes(RouteTable.Routes);

    }

}

然后兴冲冲的按下了F5.嗯主页如愿出来了,输入Service的Url,也很正常。看来一切正常。兴奋中。随便点击了个连接。接着杯具出现了。

http://localhost:3315/Uap?action=About&controller=Home 这……这……这是什么地址?我怎么没见过。囧啊。

……

…………

想了半天也没搞清楚到底怎么回事。

检查代码也没法现问题。

<ul id="menu">
									

    <li>@Html.ActionLink("Home""Index""Home")</li>
																		

    <li>@Html.ActionLink("Application""Index""Application")</li>
																		

    <li>@Html.ActionLink("About""About""Home")</li>
																		

</ul>
							

我发誓,这些代码在加入WCF Rest Service之前是正常工作的。

看来是

RouteTable.Routes.Add(new ServiceRoute("Uap"new WebServiceHostFactory(), typeof(Service.UapService)));

这行代码搞的鬼。

我把这行代码放在

RegisterRoutes(RouteTable.Routes);

下面之后发现,连接的URL到是正常了,可WCF Rest Service又不能工作了。真是活见鬼了。

百思不得其果后干脆一不做二不休,下载了MVC的源代码。

在稀里哗啦的一阵F5加F11后,终于发现问题所在了。

原来ActionLink方法在生成Url的时候会轮询所有的Route,要求符合条件的Route生成指定参数的Url并返回第一个生成值,结果蛋疼的ServiceRoute不知道是脑袋烧坏了还是怎么的。给我返回了/Uap?action=About&controller=Home这么个悲催的地址。ActionLink方法就原模原样的给输出到页面了(也不看看是不是上当了,真是个傻二哥)。

看来问题的症结已经找到了。现在该想办法解决了。

最直接的方法就是修改MVC的源代码,不过在看了整个MVC项目的源代码后,我放弃了这个疯狂的想法。

不过到是发现了一个方法,那就是把

RouteTable.Routes.Add(new ServiceRoute("Uap"new WebServiceHostFactory(), typeof(Service.UapService)));

放在所有MVC的Route之后所有连接的Url就都正常了。

可是这样WCF Rest Service的Route地址就会被

routes.MapRoute(

            "Default"// Route name

            "{controller}/{action}/{id}"// URL with parameters

            new { controller = "Home", action = "Index", id = UrlParameter.Optional }

拦截。

头疼……

看来得想办法让MVC 的Route忽略ServiceRoute的Route地址。该怎么做呢。

忽略?对,忽略!

说做就做。

routes.IgnoreRoute("/Uap/{*pathInfo}");

这下应该可以了吧?

按下F5,首页正常;链接Url正常;Wcf Service?不正常。靠……

仔细看看,靠……

头疼医脚,这个IgnoreRoute和MVC压根就没半毛钱关系。

routes.IgnoreRoute("/Uap/{*pathInfo}");

干脆直接把Wcf Service给封杀了。

看来这样还是不行,难道真的要去修改MVC的源代码吗?

我可不想这么做,再研究研究好了。我宁愿发半个小时的呆也不愿多写一行代码,动手毕竟没有动脑那么有成就感。(一个该被鄙视的懒鬼,发半个小时呆就为了想方设法少写一行代码。)

百无聊赖下翻起了MSDN,突然记起MapRoute方法有一个指定路由规则的参数,这个参数可以传递一个正则表达式来约束路由规则。

看来我已经找到了解决问题的金钥匙了。

于是写如下代码:

 routes.MapRoute(

     "Default"// Route name
								

     "{controller}/{action}/{id}"// URL with parameters
								

     new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
														

     new { controller = @"^\b(?!uap)\w*\b$" }

规则很简单,忽略所有路径中有uap字符的路径。

运行之后发现,一切正常,终于解决问题。

贴上源代码:

public class MvcApplication : System.Web.HttpApplication
											

{

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)

    {

        filters.Add(new HandleErrorAttribute());

    }

 

    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
														

            new { controller = @"^\b(?!uap)\w*\b$" }

        );

 

    }

 

    protected void Application_Start()

    {

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);

        RegisterRoutes(RouteTable.Routes);

        RouteTable.Routes.Add(new ServiceRoute("Uap"new WebServiceHostFactory(), typeof(Service.UapService)));

    }

}

 

收工,睡觉。

迷糊中……猛然惊醒,靠……忘了洗澡!!!!!

posted @ 2011-06-13 22:16  牧野  阅读(...)  评论(... 编辑 收藏