我偶然发现了这个问题,试图自己找到答案,因为我确实找到了解决方法,所以我想我会回答它。
我需要这个的原因是因为我正在将一个旧的 ASP.NET 网站转换为 ASP.NET MVC,并且出于兼容性目的,我需要一个在特定 URL 上可用的 Web 服务。但是,该 URL 的路径现在由新站点中的控制器处理,因此我不能有一个具有相同名称的物理目录(因为这将阻止控制器为具有该路径的其他 URL 调用,而不是 Web 服务)。
RouteCollection.MapPageRoute 使用的PageRouteHandler 确实要求目标路径的处理程序源自System.Web.Page,而Web 服务则不是这种情况。因此,有必要创建一个自定义页面处理程序:
using System;
using System.Web;
using System.Web.Routing;
using System.Web.Services.Protocols;
public class ServiceRouteHandler : IRouteHandler
{
private readonly string _virtualPath;
private readonly WebServiceHandlerFactory _handlerFactory = new WebServiceHandlerFactory();
public ServiceRouteHandler(string virtualPath)
{
if( virtualPath == null )
throw new ArgumentNullException("virtualPath");
if( !virtualPath.StartsWith("~/") )
throw new ArgumentException("Virtual path must start with ~/", "virtualPath");
_virtualPath = virtualPath;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// Note: can't pass requestContext.HttpContext as the first parameter because that's
// type HttpContextBase, while GetHandler wants HttpContext.
return _handlerFactory.GetHandler(HttpContext.Current, requestContext.HttpContext.Request.HttpMethod, _virtualPath, requestContext.HttpContext.Server.MapPath(_virtualPath));
}
}
此路由处理程序将根据请求和映射的服务虚拟路径为 Web 服务创建适当的处理程序。
您现在可以为 Web 服务添加路由,如下所示:
routes.Add("RouteName", new Route("path/to/your/service", new RouteValueDictionary() { { "controller", null }, { "action", null } }, new ServiceRouteHandler("~/actualservice.asmx")));
注意:您必须在路由值字典中指定控制器和操作值(即使它们设置为 null),否则 Html.ActionLink 助手将始终为每个链接使用此路由(除非找到匹配项在此路线之前的列表中)。由于您可能希望在默认 MVC 路由之前添加此路由,因此不要以这种方式匹配它,这一点很重要。
当然,您可以创建自己的扩展方法来减轻此任务:
public static Route MapServiceRoute(this RouteCollection routes, string routeName, string url, string virtualPath)
{
if( routes == null )
throw new ArgumentNullException("routes");
Route route = new Route(url, new RouteValueDictionary() { { "controller", null }, { "action", null } }, new ServiceRouteHandler(virtualPath));
routes.Add(routeName, route);
return route;
}
之后你可以简单地做:
routes.MapServiceRoute("RouteName", "path/to/your/service", "~/actualservice.asmx");
我希望这对某人有所帮助,尽管这个问题已经很老了。 :)