使用ASP.NET MVC中的路由映射到ASMX服务 [英] Mapping to an ASMX service using routing in ASP.NET MVC

查看:41
本文介绍了使用ASP.NET MVC中的路由映射到ASMX服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有任何方法可以像使用页面一样(使用 routes.MapPageRoute()方法)将URL映射到ASMX服务.

当我尝试简单地通过将MapPageRoute指向我的服务来执行此操作时,会出现错误

类型'MvcApplication1.Services.EchoService'不继承自'System.Web.UI.Page'.

Matthias.

解决方案

我偶然发现了这个问题,试图自己找到答案,并且由于我确实找到了解决问题的方法,所以我想回答一下./p>

之所以需要它,是因为我正在将一个旧的ASP.NET网站转换为ASP.NET MVC,并且出于兼容性目的,我需要在特定URL上可用的Web服务.但是,该URL的路径现在由新站点中的Controller处理,因此我无法使用具有相同名称的物理目录(因为这将阻止对具有该路径而不是Web服务的其他URL调用该控制器.).

RouteCollection.MapPageRoute 使用的 PageRouteHandler 确实要求目标路径的处理程序派生自 System.Web.Page ,Web服务则不是这种情况.因此,必须创建一个自定义页面处理程序:

 使用系统;使用System.Web;使用System.Web.Routing;使用System.Web.Services.Protocols;公共类ServiceRouteHandler:IRouteHandler{私有只读字符串_virtualPath;私有只读WebServiceHandlerFactory _handlerFactory = new WebServiceHandlerFactory();公共ServiceRouteHandler(字符串virtualPath){if(virtualPath == null)抛出新的ArgumentNullException("virtualPath");if(!virtualPath.StartsWith(〜/"))抛出新的ArgumentException(虚拟路径必须以〜/开头," virtualPath);_virtualPath = virtualPath;}公共IHttpHandler GetHttpHandler(RequestContext requestContext){//注意:不能将requestContext.HttpContext作为第一个参数传递,因为//键入HttpContextBase,而GetHandler则需要HttpContext.返回_handlerFactory.GetHandler(HttpContext.Current,requestContext.HttpContext.Request.HttpMethod,_virtualPath,requestContext.HttpContext.Server.MapPath(_virtualPath));}} 

此路由处理程序将根据请求和服务的映射虚拟路径为Web服务创建适当的处理程序.

您现在可以为Web服务添加路由,如下所示:

  routes.Add("RouteName",新Route("path/to/your/service",新RouteValueDictionary(){{"controller",null},{"action",null}},新ServiceRouteHandler(〜/actualservice.asmx")))); 

注意:您必须在路由值字典中指定控制器和操作值(即使它们设置为null),否则 Html.ActionLink 帮助器将始终对每个单个路由使用此路由链接(除非在此路线之前的列表中找到匹配项).由于您可能想在默认的MVC路由之前添加此路由,因此不要以这种方式进行匹配很重要.

当然,您可以创建自己的扩展方法来减轻此任务:

 公共静态Route MapServiceRoute(此RouteCollection路由,字符串routeName,字符串url,字符串virtualPath){if(路线== null)抛出新的ArgumentNullException("routes");路由route = new Route(url,new RouteValueDictionary(){{"controller",null},{"action",null}},new ServiceRouteHandler(virtualPath));route.Add(routeName,route);回程路线;} 

之后,您可以简单地执行以下操作:

  routes.MapServiceRoute("RouteName",路径/到/您的/服务",〜/actualservice.asmx"); 

尽管存在这个问题,我希望这对某人有帮助.:)

I wonder if there's any way to map a URL to ASMX service much like it is done with pages (using routes.MapPageRoute() method).

When I tried to do it simply by pointing the MapPageRoute to my service I get the error

Type 'MvcApplication1.Services.EchoService' does not inherit from 'System.Web.UI.Page'.

Matthias.

解决方案

I stumbled upon this question trying to find the answer myself, and since I did figure out a way to do it, I figured I'd answer it.

The reason I needed this is because I'm converting an old ASP.NET website to ASP.NET MVC, and for compatibility purposes I need a web service available at a specific URL. However, the path of that URL is now handled by a Controller in the new site, so I cannot have a physical directory with the same name (since that will prevent the controller from being invoked for other URLs with that path other than the web service).

The PageRouteHandler, which is used by RouteCollection.MapPageRoute, indeed requires that the handler for the target path derives from System.Web.Page, which isn't the case for web services. So instead, it is necessary to create a custom page handler:

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

This route handler will create an appropriate handler for the web service based on the request and mapped virtual path of the service.

You can add a route for a web service now as follows:

routes.Add("RouteName", new Route("path/to/your/service", new RouteValueDictionary() { { "controller", null }, { "action", null } }, new ServiceRouteHandler("~/actualservice.asmx")));

Note: you must specify the controller and action values in the route value dictionary (even though they're set to null), otherwise the Html.ActionLink helper will always use this route for every single link (unless a match was found in the list before this route). Since you probably want to add this route before the default MVC route, it's important that it doesn't get matched that way.

Of course, you can create your own extension method to alleviate this task:

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

After which you can simply do:

routes.MapServiceRoute("RouteName", "path/to/your/service", "~/actualservice.asmx");

I hope this helps someone, despite the age of this question. :)

这篇关于使用ASP.NET MVC中的路由映射到ASMX服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆