有没有支持JavaScript视图的ASP.Net MVC视图引擎?

4

我希望在ASP.Net MVC服务器端生成一些JavaScript。有哪个视图引擎支持这样做吗?理想情况下,我希望能够从类似以下URL的地方获取JavaScript:

http://myapp/controller/action.js

我看过MonoRail项目,他们似乎有这个功能,但是文档非常不完善,我找不到任何与ASP.Net MVC的端口。

编辑:想法是能够通过使用类似以下url的标准HTML来呈现页面:

http://myapp/controller/action

使用问题中的第一个URL,可以将JS(特别是ExtJS组件)作为IT技术相关内容进行翻译。控制器中只有一个操作,但有两个视图:一个用于HTML,一个用于JS。

编辑2:我基本上想要实现与CakePHP中路由扩展解析/请求处理相同的结果。

6个回答

3

我希望将这个想法扩展到不仅允许JavaScript视图,而且几乎可以适用于任何类型的文档。要使用它,您只需将*.js URL的视图放在控制器视图文件夹的子文件夹中:

\Views
+-\MyController
  +-\js
  | +-Index.aspx <- This view will get rendered if you request /MyController/Index.js
  +-Index.aspx

这个类是任何类型的ViewEngine的装饰器,因此您可以将其与NVelocity/WebForms/任何其他技术一起使用:

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);
    }
}

然后,在你的 Global.asax.cs 文件中:
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);
}

感谢大家对此的帮助!

2

2

根据您的编辑,我将尝试提供新的答案,假设您需要为ExtJS获取JSON数据。我刚在我正在构建的应用程序中进行了测试,它可以正常工作。首先,您需要两个路由。

{controller}/{action}.{format}

{controller}/{action}

现在,控制器类有一个Json方法,可以序列化任何您想要的对象,它是JsonResult类型,因此您只需使用:

public ActionResult List(string format) {

    // logic here

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

}

这大致就是我想做的事情,没错...不过,我更倾向于将视图决策与控制器分离,因此我制作了一个自定义视图引擎包装器。 - Jacob

1

我曾经需要做类似的事情,我使用了MVCContrib中的nvelocity视图引擎 - 从技术上讲,你可以使用默认的aspx视图引擎,但我发现nvelocity语法更加直观易懂(如果你以前没有使用过也不用担心 - 我花了大约10分钟弄清楚它!)。

然后,您只需要向路由表添加一个路由来处理将您的.js URL定向到操作!

编辑

无法验证此内容,因为我手头没有Visual Studio,但是对于路由,您可能会有类似以下的内容:

RouteTable.Routes.Add(new Route
{
   Url = "[controller]/[action].js",
   Defaults = new { controller="home", requestType="javascript" }, // Whatever...
   RouteHandler = typeof(MvcRouteHandler)
});

RouteTable.Routes.Add(new Route
{
   Url = "[controller]/[action]",
   Defaults = new { controller="home"}, // Whatever...
   RouteHandler = typeof(MvcRouteHandler)
});

以 .js 结尾的请求应该通过第一个路由处理 - 没有扩展名的请求则会落入第二个路由。

然后您的操作可以具有 requestType 参数:

public ActionResult MyAction (RequestType requestType)
{
  if(requestType == RequestType.JavaScript)
  {
     ... new nvelocity view to render javascript
  }
  else
  {
     ... 
  }
}

关于目录结构 - 你需要自己决定!这并不是因为我不想帮忙,而是因为你有灵活性可以按照自己的意愿进行设置!

你能否给出一个示例,说明我可以使用哪条路线以及可能的目录结构? - Jacob
这是一个很好的想法。我基本上将其抽象到视图引擎层面,使其对我的控制器透明化。 - Jacob

1
你不一定需要视图引擎,只需返回纯文本结果。

这是一个控制器(MonoRail),我用它来呈现JavaScript对象中的一些用户区域设置:
[ControllerDetails("js")]
public class JavascriptController : Controller
{
    private ISessionContext sessionContext;

    public JavascriptController(ISessionContext sessionContext)
    {
        this.sessionContext = sessionContext;
    }

    public void CultureInfo()
    {
        var scriptformat = @"var cultureInfo = {0};";
        var json = Context.Services.JSONSerializer.Serialize(getJSONiZableCultureInfo(sessionContext.CurrentCulture));
        RenderText(String.Format(scriptformat, json));
    }

    object getJSONiZableCultureInfo(System.Globalization.CultureInfo  culture)
    {
        return new
                        {   // add more there
                            culture.NumberFormat
                        };
    }
}

对于更复杂的事情,原始文本渲染可能会有问题,任何视图引擎都可以使用。

此外,您不必强制使用.js扩展名将URL放入脚本标记中。


关于这个扩展:我知道,但使用起来相当不错(你可以立即知道你正在获取的内容类型)。请参见http://tryingthisagain.com/2007/12/14/aspnet-mvc-routing-limitations/。 - Jacob
我错过了你问题的要点(现在通过编辑更清晰了)。看起来你在谈论一些JavaScript助手。同样,这可以通过定义某种DSL以输出JavaScript的简单助手类来实现。对于Monorail,请参见:http://markmail.org/message/zzjxhpjwxsnib2uk - smoothdeveloper
那是我所提到的 Monorail 的一部分。我正在寻找类似于 Monorail 中 .njs 视图处理 JS 视图的东西,用于 ASP。 - Jacob

0

如果您只想根据ViewData生成JavaScript,可以创建自己的自定义结果。这里是一个例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接