我正在尝试为我的ASP.NET MVC 5项目设置一些路由。
现在我有一些奇怪的行为:
/Home/About
已正确路由/Home/Index
被路由到/XmlRpc?action=Index&controller=Blog
/HOme/Index
有效(是的,我
发现由于一个错字) - 我一直认为路线是案例
不敏感?Url.Action("Foo","Bar")
也会创建/XmlRpc?action=Foo&controller=Bar
这是我的RouteConfig
文件:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("XmlRpc", new Route("XmlRpc", new MetaWeblogRouteHandler()));
routes.MapRoute("Post", "Post/{year}/{month}/{day}/{id}", new {controller = "Blog", action = "Post"}, new {year = @"\d{4,4}", month = @"\d{1,2}", day = @"\d{1,2}", id = @"(\w+-?)*"});
routes.MapRoute("Posts on Day", "Post/{year}/{month}/{day}", new {controller = "Blog", action = "PostsOnDay"}, new {year = @"\d{4,4}", month = @"\d{1,2}", day = @"\d{1,2}"});
routes.MapRoute("Posts in Month", "Post/{year}/{month}", new {controller = "Blog", action = "PostsInMonth"}, new {year = @"\d{4,4}", month = @"\d{1,2"});
routes.MapRoute("Posts in Year", "Post/{year}", new {controller = "Blog", action = "PostsInYear"}, new {year = @"\d{4,4}"});
routes.MapRoute("Post List Pages", "Page/{page}", new {controller = "Blog", action = "Index"}, new {page = @"\d{1,6}"});
routes.MapRoute("Posts by Tag", "Tag/{tag}", new {controller = "Blog", action = "PostsByTag"}, new {id = @"(\w+-?)*"});
routes.MapRoute("Posts by Category", "Category/{category}", new {controller = "Blog", action = "PostsByCategory"}, new {id = @"(\w+-?)*"});
routes.MapRoute("Default", "{controller}/{action}/{id}", new {controller = "Blog", action = "Index", id = UrlParameter.Optional});
}
这就是MetaWeblogRouteHandler
:
public class MetaWeblogRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MetaWeblog();
}
}
基本上我想通过/ XmlRpc通过XmlRpc处理程序获得通常的ASP.NET MVC路由行为(/ controller / action)+我定义的永久链接+ XML-RPC处理的自定义路由。
由于参数与Default
路线中定义的参数相同,我尝试删除路线,但没有成功。
有什么想法吗?
更新
调用/Home/Index
时,AppRelativeCurrentExecutionFilePath
设置为"~/XmlRpc"
,因此XmlRpc路由合法选择。似乎有什么东西搞乱了请求?
Update2:除了一种情况之外,问题就解决了:当通过Visual Studio for Debug启动IE时,它仍然失败。在其他所有情况下,它现在都可以工作(是的,我检查了浏览器缓存,甚至在不同的机器上尝试过以确定; IE从VS =失败开始,所有其他组合都很好)。无论如何,因为它现在适用于最终用户,我对此感到满意;)
答案 0 :(得分:5)
执行Url.Action("Foo","Bar")
时,MVC将根据您的输入创建一个路由值集合(在这种情况下,action = Foo,controller = Bar)然后它会查看您的路由,尝试匹配匹配的路由基于其细分和默认值。
您的XmlRpc路由没有分段且没有默认值,并且是第一个定义的路由。这意味着在使用@Url.Action
,@Html.ActionLink
等生成网址时,它始终是第一个匹配。
在生成网址时阻止该路由匹配的快速方法是添加默认控制器参数(使用您确定永远不会使用的控制器名称)。例如:
routes.Add("XmlRpc", new Route("XmlRpc", new RouteValueDictionary() { { "controller", "XmlRpc" } }, new MetaWeblogRouteHandler()));
现在执行Url.Action("Foo","Bar")
时,您将获得预期的/Bar/Foo
网址,因为“条形图”与路径定义中的默认控制器值“XmlRpc”不匹配。
然而,这看起来有点黑客。
更好的选择是创建自己的RouteBase
课程。这只会关注网址/XmlRpc
,然后使用MetaWeblogRouteHandler
投放,并在使用Html和Url帮助生成链接时将被忽略:
public class XmlRpcRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//The route will only be a match when requesting the url ~/XmlRpc, and in that case the MetaWeblogRouteHandler will handle the request
if (httpContext.Request.AppRelativeCurrentExecutionFilePath.Equals("~/XmlRpc", StringComparison.CurrentCultureIgnoreCase))
return new RouteData(this, new MetaWeblogRouteHandler());
//If url is other than /XmlRpc, return null so MVC keeps looking at the other routes
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//return null, so this route is skipped by MVC when generating outgoing Urls (as in @Url.Action and @Html.ActionLink)
return null;
}
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Add the route using our custom XmlRpcRoute class
routes.Add("XmlRpc", new XmlRpcRoute());
... your other routes ...
}
但是,最后您要创建一条路径,只是为了在单个网址的MVC流程外运行IHttpHandler
。你甚至在努力保持这条路线不会干扰其余的MVC组件,比如使用帮助器生成URL时。
然后,您可以直接在web.config文件中添加该模块的处理程序,同时在MVC路由中为/XmlRpc
添加忽略规则:
<configuration>
...
<system.webServer>
<handlers>
<!-- Make sure to update the namespace "WebApplication1.Blog" to whatever your namespace is-->
<add name="MetaWebLogHandler" verb="POST,GET" type="WebApplication1.Blog.MetaWeblogHandler" path="/XmlRpc" />
</handlers>
</system.webServer>
</configuration>
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Make sure MVC ignores /XmlRpc, which will be directly handled by MetaWeblogHandler
routes.IgnoreRoute("XmlRpc");
... your other routes ...
}
使用这三种方法中的任何一种,这就是我得到的:
/Home/Index
呈现HomeController
/
呈现BlogController
@Url.Action("Foo","Bar")
生成网址/Bar/Foo
@Html.ActionLink("MyLink","Foo","Bar")
呈现以下html:<a href="/Bar/Foo">MyLink</a>
/XmlRcp
呈现描述MetaWeblogHandler及其可用方法的视图,其中有一个可用的方法(blog.index,不带参数并返回字符串)
为了测试这个,我创建了一个新的空MVC 5应用程序,添加了NuGet包 xmlrpcnet-server 。
我创建了HomeController
和BlogController
,两者都有索引操作,我创建了以下MetaWeblog类:
public interface IMetaWeblog
{
[XmlRpcMethod("blog.index")]
string Index();
}
public class MetaWeblogHandler : XmlRpcService, IMetaWeblog
{
string IMetaWeblog.Index()
{
return "Hello World";
}
}
public class MetaWeblogRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MetaWeblogHandler();
}
}