Can ASP.NET Routing be used to create “clean” URLs for .ashx (IHttpHander) handlers?

前端 未结 5 1895
温柔的废话
温柔的废话 2020-11-30 03:19

I have some REST services using plain old IHttpHandlers. I\'d like to generate cleaner URLs, so that I don\'t have the .ashx in the path. Is there a way to us

5条回答
  •  余生分开走
    2020-11-30 04:02

    Yeah, I noticed that, too. Perhaps there is a built-in ASP.NET way to do this, but the trick for me was to create a new class derived from IRouteHandler:

    using System;
    using System.IO;
    using System.Reflection;
    using System.Text.RegularExpressions;
    using System.Web;
    using System.Web.Routing;
    
    namespace MyNamespace
    {
        class GenericHandlerRouteHandler : IRouteHandler
        {
            private string _virtualPath;
            private Type _handlerType;
            private static object s_lock = new object();
    
            public GenericHandlerRouteHandler(string virtualPath)
            {
                _virtualPath = virtualPath;
            }
    
            #region IRouteHandler Members
    
            public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)
            {
                ResolveHandler();
    
                IHttpHandler handler = (IHttpHandler)Activator.CreateInstance(_handlerType);
                return handler;
            }
    
            #endregion
    
            private void ResolveHandler()
            {
                if (_handlerType != null)
                    return;
    
                lock (s_lock)
                {
                    // determine physical path of ashx
                    string path = _virtualPath.Replace("~/", HttpRuntime.AppDomainAppPath);
    
                    if (!File.Exists(path))
                        throw new FileNotFoundException("Generic handler " + _virtualPath + " could not be found.");
    
                    // parse the class name out of the .ashx file
                    // unescaped reg-ex: (?<=Class=")[a-zA-Z\.]*
                    string className;
                    Regex regex = new Regex("(?<=Class=\")[a-zA-Z\\.]*");
                    using (var sr = new StreamReader(path))
                    {
                        string str = sr.ReadToEnd();
    
                        Match match = regex.Match(str);
                        if (match == null)
                            throw new InvalidDataException("Could not determine class name for generic handler " + _virtualPath);
    
                        className = match.Value;
                    }
    
                    // get the class type from the name
                    Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
                    foreach (Assembly asm in asms)
                    {
                        _handlerType = asm.GetType(className);
                        if (_handlerType != null)
                            break;
                    }
    
                    if (_handlerType == null)
                        throw new InvalidDataException("Could not find type " + className + " in any loaded assemblies.");
                }
            }
        }
    }
    

    To create a route for an .ashx:

    IRouteHandler routeHandler = new GenericHandlerRouteHandler("~/somehandler.ashx");
    Route route = new Route("myroute", null, null, null, routeHandler);
    RouteTable.Routes.Add(route);
    

    The code above may need to be enhanced to work with your route arguments, but it's starting point. Comments welcome.

提交回复
热议问题