Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an ASP.Net MVC view engine that supports JavaScript views?

I would like to generate some JavaScript on the server side in ASP.Net MVC. Is there a view engine that supports this? Ideally I would like to be able to get JavaScript from an url like:

http://myapp/controller/action.js

I've looked at the MonoRail project, and they seem to have this feature, but it's very lacking in documentation, and I can't find any ports to ASP.Net MVC.

Edit: The idea is to be able to render a page both as standard HTML by using a url like:

http://myapp/controller/action

and as js (specifically an ExtJS component) by using the first url in the question. There would be only a single action in the controller, but two views: one for HTML and one for JS.

Edit 2: I basically wanted to achieve the same result as router extension parsing/request handling in CakePHP.

like image 798
Jacob Avatar asked Jan 23 '23 23:01

Jacob


2 Answers

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!

like image 145
Jacob Avatar answered May 04 '23 01:05

Jacob


Based on your edit I'll try with a new answer asumming you need json data for ExtJS. I've just tested it in the app I'm building and it works fine. First you need two routes

{controller}/{action}.{format}

{controller}/{action}

Now the Controller class has a Json method to serialize whatever object you want and it's a JsonResult so you can just use:

public ActionResult List(string format) {

    // logic here

    if (string.IsNullOrEmpty(format)) {
        return View();
    } else if (format == "js") {
        return Json(object_to_serialize);
    }

}
like image 27
Eduardo Campañó Avatar answered May 04 '23 01:05

Eduardo Campañó