可以使用ASP.NET路由为.ashx(IHttpHander)处理程序创建“干净”的URL吗?

我有一些REST服务使用简单的老式IHttpHandlers。我想要生成更干净的URL,这样我就没有路径中的.ashx。有没有办法使用ASP.NET路由来创建映射到ashx处理程序的路由?我以前看过这些类型的路由:
// Route to an aspx page
RouteTable.Routes.MapPageRoute("route-name","some/path/{arg}","~/Pages/SomePage.aspx");

// Route for a WCF service
RouteTable.Routes.Add(new ServiceRoute("Services/SomeService",new WebServiceHostFactory(),typeof(SomeService)));

尝试使用RouteTable.Routes.MapPageRoute()生成错误(处理程序不从页面派生)。 System.Web.Routing.RouteBase只有两个派生类:ServiceRoute用于服务,DynamicDataRoute用于MVC。我不知道MapPageRoute()是做什么的(反射器没有显示方法体,它只是显示“性能关键到内联这种类型的方法跨越NGen图像边界”)。

我看到RouteBase没有密封,并且有一个比较简单的界面:

public abstract RouteData GetRouteData(HttpContextBase httpContext);

public abstract VirtualPathData GetVirtualPath(RequestContext requestContext,RouteValueDictionary values);

所以也许我可以做自己的HttpHandlerRoute。我会给出一个镜头,但是如果有人知道现有或内置的映射到IHttpHandlers的路由,那将是巨大的。

解决方法

好的,我一直在想这个,因为我原来问这个问题,我终于有一个解决方案,只是我想要的。然而,有一些前面的解释是由于。 IHttpHandler是一个非常基本的界面:
bool IsReusable { get; }
void ProcessRequest(HttpContext context)

没有内置的访问路径数据的属性,路由数据也不能在上下文或请求中找到。 System.Web.UI.Page对象具有RouteData属性,ServiceRoutes执行解释您的UriTemplates的所有工作,并将值传递到内部正确的方法,ASP.NET MVC提供了自己访问路由数据的方式。即使您有一个RouteBase,(a)确定传入的URL是否与您的路由匹配,(b)解析该URL以从您的IHttpHandler中提取要使用的所有个别值,则没有简单的方法可以通过路由数据到您的IHttpHandler。如果你想保持你的IHttpHandler“纯”,可以这么说,它负责处理url,以及如何从中提取任何值。在这种情况下,RouteBase实现仅用于确定是否应该使用您的IHttpHandler。

然而,一个问题依然存在。一旦RouteBase确定传入的URL与您的路由匹配,就会传递给一个IRouteHandler,它会创建要处理您的请求的IHttpHandler的实例。但是,一旦你在你的IHttpHandler,context.Request.CurrentExecutionFilePath的价值是误导的。这是来自客户端的URL,减去查询字符串。所以这不是你的.ashx文件的路径。而且,您的路由的任何部分(如方法的名称)都将是该路径的一部分,这些部分将是执行文件路径值的一部分。如果您在IHttpHandler中使用UriTemplates来确定IHttpHandler中哪个特定方法应该处理请求,那么这可能是一个问题。

示例:如果您在/myApp/services/myHelloWorldHandler.ashx中有.ashx处理程序
你有这条路线映射到处理程序:“services / hello / {name}”
你导航到这个url,试图调用你的处理程序的SayHello(string name)方法:
http://localhost/myApp/services/hello/SayHello/Sam

那么你的CurrentExecutionFilePath将是:/ myApp / services / hello / Sam。它包含路由url的一部分,这是一个问题。您希望执行文件路径与您的路由网址匹配。 RouteBase和IRouteHandler的以下实现处理这个问题。

在粘贴2个类之前,这里有一个非常简单的用法示例。请注意,RouteBase和IRouteHandler的这些实现将实际上适用于甚至没有.ashx文件的IHttpHandlers,这是非常方便的。

// A "headless" IHttpHandler route (no .ashx file required)
RouteTable.Routes.Add(new GenericHandlerRoute<HeadlessService>("services/headless"));

这将导致所有匹配“服务/无头”路由的传入URL被切换到HeadlessService IHttpHandler的新实例(HeadlessService只是这种情况下的一个例子,这将是您想要传递的任何IHttpHandler实现) 。

好的,所以这里是路由类的实现,注释和全部:

/// <summary>
/// For info on subclassing RouteBase,check Pro Asp.NET MVC Framework,page 252.
/// Google books link: http://books.google.com/books?id=tD3FfFcnJxYC&pg=PA251&lpg=PA251&dq=.net+RouteBase&source=bl&ots=IQhFwmGOVw&sig=0TgcFFgWyFRVpXgfGY1dIUc0VX4&hl=en&ei=z61UTMKwF4aWsgPHs7XbAg&sa=X&oi=book_result&ct=result&resnum=6&ved=0CC4Q6AEwBQ#v=onepage&q=.net%20RouteBase&f=false
/// 
/// It explains how the asp.net runtime will call GetRouteData() for every route in the route table.
/// GetRouteData() is used for inbound url matching,and should return null for a negative match (the current requests url doesn't match the route).
/// If it does match,it returns a RouteData object describing the handler that should be used for that request,along with any data values (stored in RouteData.Values) that
/// that handler might be interested in.
/// 
/// The book also explains that GetVirtualPath() (used for outbound url generation) is called for each route in the route table,but that is not my experience,/// as mine used to simply throw a NotImplementedException,and that never caused a problem for me.  In my case,I don't need to do outbound url generation,/// so I don't have to worry about it in any case.
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericHandlerRoute<T> : RouteBase where T : IHttpHandler,new()
{
    public string RouteUrl { get; set; }


    public GenericHandlerRoute(string routeUrl)
    {
        RouteUrl = routeUrl;
    }


    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        // See if the current request matches this route's url
        string baseUrl = httpContext.Request.CurrentExecutionFilePath;
        int ix = baseUrl.IndexOf(RouteUrl);
        if (ix == -1)
            // Doesn't match this route.  Returning null indicates to the asp.net runtime that this route doesn't apply for the current request.
            return null;

        baseUrl = baseUrl.Substring(0,ix + RouteUrl.Length);

        // This is kind of a hack.  There's no way to access the route data (or even the route url) from an IHttpHandler (which has a very basic interface).
        // We need to store the "base" url somewhere,including parts of the route url that are constant,like maybe the name of a method,etc.
        // For instance,if the route url "myService/myMethod/{myArg}",and the request url were "http://localhost/myApp/myService/myMethod/argValue",// the "current execution path" would include the "myServer/myMethod" as part of the url,which is incorrect (and it will prevent your UriTemplates from matching).
        // Since at this point in the exectuion,we know the route url,we can calculate the true base url (excluding all parts of the route url).
        // This means that any IHttpHandlers that use this routing mechanism will have to look for the "__baseUrl" item in the HttpContext.Current.Items bag.
        // TODO: Another way to solve this would be to create a subclass of IHttpHandler that has a BaseUrl property that can be set,and only let this route handler
        // work with instances of the subclass.  Perhaps I can just have RestHttpHandler have that property.  My reticence is that it would be nice to have a generic
        // route handler that works for any "plain ol" IHttpHandler (even though in this case,you have to use the "global" base url that's stored in HttpContext.Current.Items...)
        // Oh well.  At least this works for now.
        httpContext.Items["__baseUrl"] = baseUrl;

        GenericHandlerRouteHandler<T> routeHandler = new GenericHandlerRouteHandler<T>();
        RouteData rdata = new RouteData(this,routeHandler);

        return rdata;
    }


    public override VirtualPathData GetVirtualPath(RequestContext requestContext,RouteValueDictionary values)
    {
        // This route entry doesn't generate outbound Urls.
        return null;
    }
}



public class GenericHandlerRouteHandler<T> : IRouteHandler where T : IHttpHandler,new()
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new T();
    }
}

我知道这个答案已经很长时间了,但这不是一个容易解决的问题。核心逻辑是很容易的,诀窍在某种程度上使您的IHttpHandler知道“基本URL”,以便它可以正确地确定url的哪些部分属于路由,哪些部分是服务调用的实际参数。

这些类将用于我即将到来的C#REST库,RestCake.我希望我的路径下的路径兔洞可以帮助决定RouteBase的任何人,并使用IHttpHandlers做酷的东西。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


引言 本文从Linux小白的视角, 在CentOS 7.x服务器上搭建一个Nginx-Powered AspNet Core Web准生产应用。 在开始之前,我们还是重温一下部署原理,正如你所常见的.Net Core 部署图: 在Linux上部署.Net Core App最好的方式是在Linux机器
引言: 多线程编程/异步编程非常复杂,有很多概念和工具需要去学习,贴心的.NET提供Task线程包装类和await/async异步编程语法糖简化了异步编程方式。 相信很多开发者都看到如下异步编程实践原则: 遵守以上冷冰冰的②③条的原则,可保证异步程序按照预期状态正常运作;我们在各大编程论坛常看到违背
一. 宏观概念 ASP.NET Core Middleware是在应用程序处理管道pipeline中用于处理请求和操作响应的组件。 每个组件是pipeline 中的一环。 自行决定是否将请求传递给下一个组件 在处理管道的下个组件执行之前和之后执行业务逻辑 二. 特性和行为 ASP.NET Core处
背景 在.Net和C#中运行异步代码相当简单,因为我们有时候需要取消正在进行的异步操作,通过本文,可以掌握 通过CancellationToken取消任务(包括non-cancellable任务)。 Task&#160;表示无返回值的异步操作, 泛型版本Task&lt;TResult&gt;表示有返
HTTP基本认证 在HTTP中,HTTP基本认证(Basic Authentication)是一种允许网页浏览器或其他客户端程序以(用户名:口令) 请求资源的身份验证方式,不要求cookie,session identifier、login page等标记或载体。 - 所有浏览器据支持HTTP基本认
1.Linq 执行多列排序 OrderBy的意义是按照指定顺序排序,连续两次OrderBy,后面一个有可能会打乱前面一个的排序顺序,可能与预期不符。 要实现sql中的order by word,name类似效果; LINQ 有ThenBy可以紧接使用, ThenBy记住原本排序的值,然后再排其他值,
ASP.NET Core 核心特性:开源、跨平台、高性能是其决战JAVA的必胜法宝,最引人关注的跨平台特性 到底是怎么实现? &#xA; 本文分Unix、Windows剖析跨平台内幕,读完让你大呼过瘾。
前导 Asynchronous programming Model(APM)异步编程模型以BeginMethod(...) 和 EndMethod(...)结对出现。 IAsyncResult BeginGetResponse(AsyncCallback callback, object state
引言 最近在公司开发了一个项目,项目部署架构图如下: 思路 如图中文本所述,公司大数据集群不允许直接访问外网,需要一个网关服务器代理请求,本处服务器A就是边缘代理服务器的作用。 通常技术人员最快捷的思路是在服务器A上部署IISʺpplication Request Routing Module组件
作为一枚后端程序狗,项目实践常遇到定时任务的工作,最容易想到的的思路就是利用Windows计划任务/wndows service程序/Crontab程序等主机方法在主机上部署定时任务程序/脚本。 但是很多时候,若使用的是共享主机或者受控主机,这些主机不允许你私自安装exe程序、Windows服务程序
引言 熟悉TPL Dataflow博文的朋友可能记得这是个单体程序,使用TPL Dataflow 处理工作流任务, 在使用Docker部署的过程中, 有一个问题一直无法回避: 在单体程序部署的瞬间(服务不可用)会有少量流量无法处理;更糟糕的情况下,迭代部署的这个版本有问题,上线后无法运作, 更多的流
合格的web后端程序员,除搬砖技能,还必须会给各种web服务器配置Https,本文结合ASP.NET Core部署模型聊一聊启用Https的方式。 温故知新 目前常见的Http请求明文传输,请求可能被篡改,访问的站点可能被伪造。 HTTPS是HTTP加上TLS/SSL协议构建的可进行加密传输、身份认
长话短说 前文《解剖HttpClientFactory,自由扩展HttpMessageHandler》主要讲如何为HttpClientFactory自定义HttpMessageHandler组件, 现在来完成课后的小作业: 将重点日志字段显示到Nlog的LayoutRenderer上。 本文实现一个
引言问题 作为资深老鸟,有事没事,出去面试;找准差距、定位价值。 面试必谈哈希, Q1:什么是哈希? Q2:哈希为什么快? Q3:你是怎么理解哈希算法利用空间换取时间的? Q4:你是怎么解决哈希冲突的? Q5:你有实际用写过哈希算法吗? 知识储备 哈希(也叫散列)是一种查找算法(可用于插入),哈希算
前言 如题,有感于博客园最近多次翻车,感觉像胡子眉毛一把抓, 定位不了生产环境的问题。 抛开流程问题,思考在生产环境中如何做故障排除,&#160;发现博客园里面这方面的文章比较少。 .Net 本身是提供了sos.dll工具帮助我们在生产中故障排除,通过提供有关内部公共语言运行时(CLR)环境的信息,
.NET程序是基于.NET Framework、.NET Core、Mono、【.NET实现】开发和运行的 ,定义以上【.NET实现】的标准规范称为.NET Standard .NET Standard .NET标准是一组API集合,由上层三种【.NET实现】的Basic Class Library
长话短说 上个月公司上线了一个物联网数据科学项目,我主要负责前端接受物联网事件,并提供 参数下载。 webapp 部署在Azure云上,参数使用Azure SQL Server存储。 最近从灰度测试转向全量部署之后,日志时常收到: SQL Session超限报错。 排查 我在Azure上使用的是 S
临近年关,搜狗,360浏览器出现页面无法成功跳转,同域Cookie丢失? 也许是服务端 SameSite惹的祸。&#xA;本文揭示由于Chrome低版本内核不识别 SameSite= None, 引发的单点登录故障。
本文聊一聊TraceID的作用和一般组成,衍生出ASP. NETCore 单体和分布式程序中 TraceId 的使用方式
通过给 HttpClint请求的日志增加 TraceId,解锁自定义扩展 HttpClientFacroty 的姿势