I wanted to extend this idea to not only allow Javascript views, but more or less any type of document. To use it, you just put the views for *.js urls in a subfolder of your controller's view folder:
\Views
+-\MyController
+-\js
| +-Index.aspx <- This view will get rendered if you request /MyController/Index.js
+-Index.aspx
The class is a decorator for any type of ViewEngine, so you can use it with NVelocity/WebForms/Whatever:
public class TypeViewEngine<T> : IViewEngine where T : IViewEngine
{
private readonly T baseEngine;
public T BaseEngine
{
get { return baseEngine; }
}
public TypeViewEngine(T baseEngine)
{
this.baseEngine = baseEngine;
}
public void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"TypeViewEngine",
"{controller}/{action}.{type}",
new {controller = "Home", action = "Index", type = "html"}
);
}
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName)
{
var vars = controllerContext.RouteData.Values;
if(vars["type"] != null && vars["type"].ToString() != "html")
{
viewName = string.Format("{0}/{1}", vars["type"], viewName);
}
return baseEngine.FindView(controllerContext, viewName, masterName);
}
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName)
{
return baseEngine.FindPartialView(controllerContext, partialViewName);
}
public void ReleaseView(ControllerContext controllerContext, IView view)
{
baseEngine.ReleaseView(controllerContext, view);
}
}
Then, in your Global.asax.cs file:
protected void Application_Start()
{
var ve = new TypeViewEngine<WebFormViewEngine>(new WebFormViewEngine());
ve.RegisterRoutes(RouteTable.Routes);
RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(ve);
}
Thanks for everyone's help with this!