Created
June 11, 2010 18:56
-
-
Save chakrit/434894 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Web.Mvc; | |
using System.Web.Routing; | |
namespace MyApp | |
{ | |
public static class FluentMapRoute | |
{ | |
public static RouteCollection Using<TController> | |
(this RouteCollection routes, Action<FluentMapRouteSyntax<TController>> mapper) | |
where TController : ControllerBase | |
{ | |
mapper(new FluentMapRouteSyntax<TController>(routes)); | |
return routes; | |
} | |
} | |
public class FluentMapRouteSyntax<TController> | |
where TController : ControllerBase | |
{ | |
private static ISet<string> _namespaces; | |
private RouteCollection _routes; | |
public FluentMapRouteSyntax(RouteCollection routes) | |
{ | |
_routes = routes; | |
_namespaces = _namespaces ?? new HashSet<string>(); | |
} | |
public FluentMapRouteSyntax<TController> Handle | |
(string url, Expression<Action<TController>> action) | |
{ | |
var dict = new RouteValueDictionary(); | |
// get controller name from the type | |
var controllerType = typeof(TController); | |
var controller = controllerType.Name; | |
if (controller.EndsWith("Controller")) | |
controller = controller.Substring(0, controller.Length - "Controller".Length); | |
dict["Controller"] = controller; | |
// ensure the controller namespace is included | |
_namespaces.Add(controllerType.Namespace); | |
// get action name from the method name in the expression | |
var lambdaExpr = (LambdaExpression)action; | |
var callExpr = (MethodCallExpression)lambdaExpr.Body; | |
dict["Action"] = callExpr.Method.Name; | |
// get defaults for each arguments/params from the expression | |
// using the supplied value as the default value | |
var callArgs = callExpr.Arguments | |
.Select(arg => arg.CanReduce ? arg.Reduce() : arg) | |
.Cast<ConstantExpression>() | |
.Select(arg => arg.Value); | |
var parameters = callExpr.Method | |
.GetParameters() | |
.Select(param => param.Name); | |
var args = parameters.Zip(callArgs, Tuple.Create); | |
foreach (var pair in args) { | |
dict.Add(pair.Item1, pair.Item2); | |
} | |
// construct a new route from the finished dictionary | |
var route = new Route(url, new MvcRouteHandler()) { | |
Defaults = dict, | |
DataTokens = new RouteValueDictionary { | |
{ "namespaces", _namespaces.ToArray() } | |
} | |
}; | |
_routes.Add(route); | |
// return self to enable chaining | |
return this; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Web.Routing; | |
using ByMenu.Controllers; | |
namespace MyApp | |
{ | |
public static class Routes | |
{ | |
public static void Initialize(RouteCollection routes) | |
{ | |
routes | |
.Using<HomeController>(x => x | |
// This will map "" to Controller=HomeController and Action=Index | |
.Handle("", c => c.Index()) | |
// This will map "test/{name}" to Controller=HomeController and Action=Test | |
// with the name parameter defaults to "Hello World!" | |
.Handle("test/{name}", c => c.Test("Hello World!")) | |
) | |
// All chainable just because it's fun :) | |
.Using<FooContorller>(x => | |
{ | |
// use braces and separate lines for a little better readability | |
x.Handle("another", c => c.Action()); | |
x.Handle("url", c => c.Action2(1, 2, 3)); | |
}) | |
// Or just use another method altogether | |
.Using<BarController>(MapBarUrls); | |
} | |
// this method could as well be moved into the controller itself | |
// if you're like me and prefer a weird sense of locality of code :) | |
public static void MapBarUrls(FluentMapRouteSyntax<BarController> x) | |
{ | |
x.Handle("foo", x => x.Foo()); | |
x.Handle("bar", x => x.Bar()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment