ASP.NET Web窗体中的ASMX Web服务路由 [英] ASMX web services routing in ASP.NET Web Forms
问题描述
注意:该代码中没有MVC。纯旧的Web表单和
.asmx
Web服务。
NOTE: There is no MVC in this code. Pure old Web Forms and
.asmx
Web Service.
我继承了大型ASP.NET Web表单和我的新公司的Web Service( .asmx
)应用程序。
I have inherited a large scale ASP.NET Web Forms & Web Service (.asmx
) application at my new company.
由于某些需要,我尝试使用URL
Due to some need I am trying to do URL Routing for all Web Forms, which I was successfully able to do.
现在为 .asmx
, routes.MapPageRoute
不起作用。根据下面的文章,我创建了一个 IRouteHandler
类。代码如下:
Now for .asmx
, routes.MapPageRoute
does not work. Based on the below article, I created an IRouteHandler
class. Here's how the code looks:
using System;
using System.Web;
using System.Web.Routing;
using System.Web.Services.Protocols;
using System.Collections.Generic;
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));
}
}
http://mikeoncode.blogspot.in/2014/09/aspnet-web- form-routing-for-web.html
现在,当我通过 Global.asax
进行路由时,它适用于根文档文件,但不适用于 .asmx
文件中的Web方法。
Now when I do routing via Global.asax
, it work for the root documentation file but does not work with the Web Methods inside my .asmx
files.
routes.Add("myservice", new System.Web.Routing.Route("service/sDxcdfG3SC", new System.Web.Routing.RouteValueDictionary() { { "controller", null }, { "action", null } }, new ServiceRouteHandler("~/service/myoriginal.asmx")));
routes.MapPageRoute("", "service/sDxcdfG3SC", "~/service/myoriginal.asmx");
目标
我想映射一个 .asmx
Web方法URL,例如 www.website.com/service/myservice.asmx/fetchdata
到一个URL带有.NET路由的名称中带有 www.website.com/service/ldfdsfsdf/dsd3dfd3d
的名称。
Goal
I would like to map an .asmx
Web Method URL such as www.website.com/service/myservice.asmx/fetchdata
to a URL with obscured names in it like www.website.com/service/ldfdsfsdf/dsd3dfd3d
using .NET Routing.
推荐答案
通过路由进行此操作比在您发布的文章中稍微棘手,因为您没有不想传入的URL具有查询字符串参数,并且在没有?op = Method <的情况下,
WebServiceHandler
不会调用该方法? / code>参数。
It is slightly more tricky to do this with routing than in the article you posted because you don't want the incoming URL to have a query string parameter and it looks like the WebServiceHandler
won't call the method without an ?op=Method
parameter.
因此,有以下几个部分:
So, there are a few parts to this:
- 用于URL重写以添加
?op = Method
参数的自定义路由(ServiceRoute
) - 一个
IRouteHandler
来包装调用Web服务的WebServiceHandlerFactory
。 - 一组ex使注册容易的紧张方法。
- A custom route (
ServiceRoute
) to do URL rewriting to add the?op=Method
parameter - An
IRouteHandler
to wrap theWebServiceHandlerFactory
that calls the web service. - A set of extension methods to make registration easy.
ServiceRoute
ServiceRoute
public class ServiceRoute : Route
{
public ServiceRoute(string url, string virtualPath, RouteValueDictionary defaults, RouteValueDictionary constraints)
: base(url, defaults, constraints, new ServiceRouteHandler(virtualPath))
{
this.VirtualPath = virtualPath;
}
public string VirtualPath { get; private set; }
public override RouteData GetRouteData(HttpContextBase httpContext)
{
// Run a test to see if the URL and constraints don't match
// (will be null) and reject the request if they don't.
if (base.GetRouteData(httpContext) == null)
return null;
// Use URL rewriting to fake the query string for the ASMX
httpContext.RewritePath(this.VirtualPath);
return base.GetRouteData(httpContext);
}
}
ServiceHandler
ServiceHandler
public class ServiceRouteHandler : IRouteHandler
{
private readonly string virtualPath;
private readonly WebServiceHandlerFactory handlerFactory = new WebServiceHandlerFactory();
public ServiceRouteHandler(string virtualPath)
{
if (virtualPath == null)
throw new ArgumentNullException(nameof(virtualPath));
if (!virtualPath.StartsWith("~/"))
throw new ArgumentException("Virtual path must start with ~/", "virtualPath");
this.virtualPath = virtualPath;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// Strip the query string (if any) off of the file path
string filePath = virtualPath;
int qIndex = filePath.IndexOf('?');
if (qIndex >= 0)
filePath = filePath.Substring(0, qIndex);
// Note: can't pass requestContext.HttpContext as the first
// parameter because that's type HttpContextBase, while
// GetHandler expects HttpContext.
return handlerFactory.GetHandler(
HttpContext.Current,
requestContext.HttpContext.Request.HttpMethod,
virtualPath,
requestContext.HttpContext.Server.MapPath(filePath));
}
}
RouteCollectionExtensions
RouteCollectionExtensions
public static class RouteCollectionExtensions
{
public static void MapServiceRoutes(
this RouteCollection routes,
Dictionary<string, string> urlToVirtualPathMap,
object defaults = null,
object constraints = null)
{
foreach (var kvp in urlToVirtualPathMap)
MapServiceRoute(routes, null, kvp.Key, kvp.Value, defaults, constraints);
}
public static Route MapServiceRoute(
this RouteCollection routes,
string url,
string virtualPath,
object defaults = null,
object constraints = null)
{
return MapServiceRoute(routes, null, url, virtualPath, defaults, constraints);
}
public static Route MapServiceRoute(
this RouteCollection routes,
string routeName,
string url,
string virtualPath,
object defaults = null,
object constraints = null)
{
if (routes == null)
throw new ArgumentNullException("routes");
Route route = new ServiceRoute(
url: url,
virtualPath: virtualPath,
defaults: new RouteValueDictionary(defaults) { { "controller", null }, { "action", null } },
constraints: new RouteValueDictionary(constraints)
);
routes.Add(routeName, route);
return route;
}
}
用法
您可以使用 MapServiceRoute
一次添加一条路线(带有可选名称):
Usage
You can either use MapServiceRoute
to add the routes one at a time (with an optional name):
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings);
routes.MapServiceRoute("AddRoute", "service/ldfdsfsdf/dsd3dfd3d", "~/service/myoriginal.asmx?op=Add");
routes.MapServiceRoute("SubtractRoute", "service/ldfdsfsdf/dsd3dfd3g", "~/service/myoriginal.asmx?op=Subtract");
routes.MapServiceRoute("MultiplyRoute", "service/ldfdsfsdf/dsd3dfd3k", "~/service/myoriginal.asmx?op=Multiply");
routes.MapServiceRoute("DivideRoute", "service/ldfdsfsdf/dsd3dfd3v", "~/service/myoriginal.asmx?op=Divide");
}
}
或者,您可以拨打 MapServiceRoutes
一次映射一批Web服务路由:
Alternatively, you can call MapServiceRoutes
to map a batch of your web service routes at once:
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings);
routes.MapServiceRoutes(new Dictionary<string, string>
{
{ "service/ldfdsfsdf/dsd3dfd3d", "~/service/myoriginal.asmx?op=Add" },
{ "service/ldfdsfsdf/dsd3dfd3g", "~/service/myoriginal.asmx?op=Subtract" },
{ "service/ldfdsfsdf/dsd3dfd3k", "~/service/myoriginal.asmx?op=Multiply" },
{ "service/ldfdsfsdf/dsd3dfd3v", "~/service/myoriginal.asmx?op=Divide" },
});
}
}
注意::如果您要在应用程序中使用MVC,通常应该在这些路由之后 之后注册您的MVC路由。
NOTE: If you were to have MVC in the application, you should generally register your MVC routes after these routes.
参考:
- Creating a route for a .asmx Web Service with ASP.NET routing
- .NET 4 URL Routing for Web Services (asmx)
这篇关于ASP.NET Web窗体中的ASMX Web服务路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!