0

I need to do routing in an existing asp.net app - not an asp.net mvc (yeah I know I should convert but let's say it's not possible right now so don't tell me :) ) - how can I do routing to a normal class instead of an aspx page as all sample code I see is always with aspx page like here:

http://msdn.microsoft.com/en-us/magazine/dd347546.aspx

To precise, I want to do a bit like in MVC Controller routing : the controller for example product is a pure class you access through http://domain.com/product

user310291
  • 36,946
  • 82
  • 271
  • 487
  • To a class? Like as in App_Code/YourClass.cs? – justinlabenne Jan 07 '12 at 21:39
  • No I want to do like in MVC Controller routing : the controller for example product is a pure class you access through http://domain.com/product – user310291 Jan 07 '12 at 22:17
  • What is a pure class? A controller inherits from System.Web.Mvc.Controller whilst a Web Form inherits from System.Web.UI.Page. Both are classes, what makes the first pure and the second not? – Michiel van Oosterhout Jan 08 '12 at 00:08
  • Why not use URL Rewrite for IIS? This way you can have you URLs look like MVC URLs. – Brownman98 Jan 08 '12 at 00:20
  • I think you're mistaken when you say that a route such as http://domain.com/product is going to a pure class. Yes, it is going to a method, but that controller action is going to go look for a view (could be an .aspx or a .cshtml or anything else depending on the view engine) but it does pull in html from somewhere. If you're wanting to pull a view in from pure code and without a view associated with it, you will have to do like is mentioned below and use a handler of some sort to accomplish your goal. – Chris Jan 08 '12 at 02:31

3 Answers3

5

ASP.NET MVC and ASP.NET Web Forms share the same routing infrastructure in that both frameworks ultimately need to come up with an IHttpHandler to handle the HTTP request:

The IHttpHandler interface has been a part of ASP.NET since the beginning, and a Web Form (a System.Web.UI.Page) is an IHttpHandler.

(From the MSDN article linked in the question)

In ASP.NET MVC the System.Web.Mvc.MvcHandler class is used, which then delegates to a controller for further handling of the request. In ASP.NET Web Forms usually the System.Web.UI.Page class that represents an .aspx file is used, but a pure IHttpHandler associated with .ashx file can also be used.

So you can route to an .ashx handler as an alternative to an .aspx Web Forms page. Both implement IHttpHandler (as does MvcHandler), but with the former that's all it does. And that's as close as you can get to a 'pure class' handling a (routed) request. And since the handler part is just an interface, you are free to inherit from your own class.

<%@ WebHandler Language="C#" Class="LightweightHandler" %>

using System.Web;

public class LightweightHandler : YourBaseClass, IHttpHandler
{
  public void ProcessRequest(HttpContext context)
  {
    context.Response.ContentType = "text/plain";
    context.Response.Write("Hello world!");
  }

  public bool IsReusable { get { return false; } }
}

Notice that an IRouteHandler just needs to return an instance of IHttpHandler:

public IHttpHandler GetHttpHandler(RequestContext requestContext);

You may need to jump through some hoops to instantiate your handler using the BuildManager* if you use .ashx files. If not, you can just new up an instance of your class and return it:

public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
  // In case of an .ashx file, otherwise just new up an instance of a class here
  IHttpHandler handler = 
    BuildManager.CreateInstanceFromVirtualPath(path, typeof(IHttpHandler)) as IHttpHandler;

  // Cast to your base class in order to make it work for you
  YourBaseClass instance = handler as YourBaseClass;
  instance.Setting = 42;
  instance.DoWork();

  // But return it as an IHttpHandler still, as it needs to do ProcessRequest
  return handler;
}

See the answers to this question for much more in-depth analysis of routing pure IHttpHandlers: Can ASP.NET Routing be used to create “clean” URLs for .ashx (IHttpHander) handlers?

**I'm not entirely sure about the BuildManager example, someone please correct me if I got that part wrong*

Community
  • 1
  • 1
Michiel van Oosterhout
  • 22,839
  • 15
  • 90
  • 132
  • Thanks but still why would I be obliged to use .ashx since the official doc mentions I could use anything. I want to do like in MVC Controller routing : the controller for example product is a pure class you access through http://domain.com/product – user310291 Jan 07 '12 at 22:19
  • @user310291: if you want to have routing *like MVC*, then you need to switch to MVC .... you cannot do this in Webforms. – marc_s Jan 07 '12 at 22:26
  • As I said, I cannot switch to ASP.NET MVC, routing is supported since .NET 3.5 why can't I do it ? – user310291 Jan 07 '12 at 23:08
  • @user310291 How do you think ASP.NET MVC works? It has the MvcHandler class that **also** implements IHttpHandler. I have edited my answer with a short introduction of IHttpHandler and and a link to the ASP.NET MVC implementation of it on MSDN. But the bottom line is, you **must** implement IHttpHandler to handle requests in ASP.NET. – Michiel van Oosterhout Jan 07 '12 at 23:58
  • @michielvoo thanks, it's closer :) Still why can't I just implement IHttpHandler directly on my class instead of inheriting in a .ashx ? Also I saw IRouteHandler http://msdn.microsoft.com/fr-fr/library/system.web.routing.iroutehandler.aspx shouldn't I need it ? – user310291 Jan 08 '12 at 00:21
  • You can, as long as your IRouteHandler can instantiate it. In my example the IHttpHandler is based on an .ashx file, meaning you have to use the BuildManager and the path to the .ashx. But you can instantiate any class that implements IHttpHandler. Just make sure the IRouteHandler knows which class to create and return. – Michiel van Oosterhout Jan 08 '12 at 00:33
2

If you can't switch to ASP.NET MVC and routing .ashx handlers doesn't meet your requirements, you may want to look into Nancy, a 'lightweight web framework'.

Here's an example from the introduction (see link in previous paragraph):

public class Module : NancyModule
{
  public Module() : base("/foo")
  {
    Get["/"] = parameters => {
      return "This is the site route";
    };

    Delete["/product/{id}"] = parameters => {
      return string.Concat("You requested that the following product should be deleted: ", parameters.id);
    };
  }
}

This class will handle requests to /foo and /foo/product/42. You can also use views with this framework to render a more complex (HTML) response.

Michiel van Oosterhout
  • 22,839
  • 15
  • 90
  • 132
2

If you can update from 3.5 to 4.0, WebForms supports routing better. In Global.asax, you only need to do things like this:

void Application_Start(object sender, EventArgs e) 
{
    RouteTable.Routes.MapPageRoute("default", string.Empty, "~/default.aspx");       
}

I don't really understand the "pure class" part, but hopefully if updating to 4.0 is an option this can get you going.

justinlabenne
  • 793
  • 3
  • 6