在 ASP.NET MVC 中动态生成 Javascript、CSS

Posted

技术标签:

【中文标题】在 ASP.NET MVC 中动态生成 Javascript、CSS【英文标题】:Dynamically generated Javascript, CSS in ASP.NET MVC 【发布时间】:2013-04-12 03:07:00 【问题描述】:

ASP.NET 允许使用服务器标签(razor 或 ASPX)动态生成 html。但是除了使用内联(嵌入式)CSS / javascript之外,有没有什么好的方法可以以相同的方式生成 *.js 或 *.css 内容。如今,随着 Ajax 等技术的出现,越来越多的逻辑在 Javascript 中从服务器端转移到客户端。如果有机会使用 ASP.NET 为 HTML 生成提供的所有灵活性来动态生成 JS,那就太好了。

例如,我的 Javascript 包含 Knockout 视图模型声明,其中包含在 Javascript 渲染期间从服务器加载的初始数据,以及一些额外的 js 函数,所以在我的 Html 中而不是嵌入式脚本 em> 我想要这样的脚本引用:

<script src="~/Scripts/ContactViewModel.js?contactId=@Model.ContactId"></script>

另一个例子,开发者可能需要它是使用基于用户配置文件的 CSS。用户配置文件信息包含在 CSS 生成期间必须遵守的样式信息(字体、颜色,而不仅仅是主题),所以在我看来,我会有类似的内容:

<link href="~/Styles/CurrentUserOverrides.css" rel="stylesheet" />

CurrentUserOverrides.css 将根据认证用户的个人资料数据动态生成。

如何使用 ASP.NET MVC 做到这一点?我想找到一个解决方案,让我能够像使用 ASP.NET 创建动态 HTML 一样简单,同时具备正常工作的智能以及 VS 为 ASP.NET 视图提供的所有其他功能。

【问题讨论】:

我不确定我是否了解您想要完成的工作的好处。为什么要为特定页面生成上下文敏感的 Javascript? 您是否尝试使用 ContactViewModel.js 中的contactId(并且 123 的 ContactId 实际上是由您的视图模型呈现的)? 是的,ContactViewModel.js 需要用指定的 ContactId 从数据库中加载字段值来声明对象 【参考方案1】:

目前我找到的最佳解决方案如下:

Dynamic Javascript and CSS in ASP.NET MVC using Razor Views

您只需创建视图:CurrentUserOverrides.css.cshtml、ContactViewModel.js.cshtml。此视图将包含单个 HTML 块(&lt;script&gt;&lt;style&gt;),因此 IntelliSense 工作正常。然后您创建控制器来呈现该视图,修剪根标记并返回具有适当内容类型的内容。

【讨论】:

【参考方案2】:

CSHTML 文件中的动态 CSS

我使用 CSS cmets /* */ 注释掉一个新的 &lt;style&gt; 标记,然后我在结束样式标记之前 return;

/*<style type="text/css">/* */

    CSS GOES HERE

@return;</style>

CSHTML 文件中的动态 JS

我使用 JavaScript cmets &lt;!--// 注释掉一个新的 &lt;script&gt; 标记,然后我在结束脚本标记之前 return;

//<script type="text/javascript">

    JAVASCRIPT GOES HERE

@return;</script>

MyDynamicCss.cshtml

@
var fieldList = new List<string>();
fieldList.Add("field1");
fieldList.Add("field2");

/*<style type="text/css">/* */

@foreach (var field in fieldList) <text>

input[name="@field"]
, select[name="@field"]

    background-color: #bbb;
    color: #6f6f6f;


</text>

@return;</style>

MyDynamicJavsScript.cshtml

@
var fieldList = new List<string>();
fieldList.Add("field1");
fieldList.Add("field2");
fieldArray = string.Join(",", fieldList);



//<script type="text/javascript">

$(document).ready(function () 
    var fieldList = "@Html.Raw(fieldArray)";
    var fieldArray = fieldList.split(',');
    var arrayLength = fieldArray.length;
    var selector = '';
    for (var i = 0; i < arrayLength; i++) 
        var field = fieldArray[i];
        selector += (selector == '' ? '' : ',')
                    + 'input[name="' + field + '"]'
                  + ',select[name="' + field + '"]';            
    
    $(selector).attr('disabled', 'disabled');
    $(selector).addClass('disabled');
);
@return;</script>

无需控制器(使用视图/共享)

我将我的两个动态脚本都放入了Views/Shared/,我可以使用以下代码轻松地将它们嵌入到任何现有页面(或_Layout.cshtml)中:

<style type="text/css">@Html.Partial("MyDynamicCss")</style>
<script type="text/javascript">@Html.Partial("MyDynamicJavaScript")</script>

使用控制器(可选)

如果您愿意,可以创建一个控制器,例如

<link rel="stylesheet" type="text/css" href="@Url.Action("MyDynamicCss", "MyDynamicCode")">
<script type="text/javascript" src="@Url.Action("MyDynamicJavaScript", "MyDynamicCode")"></script>

这是控制器的外观

MyDynamicCodeController.cs(可选)

[HttpGet]
public ActionResult MyDynamicCss()

    Response.ContentType = "text/css";
    return View();


[HttpGet]
public ActionResult MyDynamicJavaScript()

    Response.ContentType = "application/javascript";
    return View();

备注

控制器版本未经测试。我只是在脑海中输入的。 在重新阅读我的答案后,我突然想到,注释掉结束标记而不是使用 cshtml @return; 可能同样容易,但我还没有尝试过。我想这是一个偏好问题。 关于我的整个回答,如果您发现任何语法错误或改进,请告诉我。

【讨论】:

多么棒的答案。谢谢你。正是我所需要的。我只是不明白棘手的// 部分。你能详细说明吗? @RoyiNamir 自动完成和颜色。在 JavaScript 示例中,Web 浏览器正在读取 JavaScript,看到 // 并忽略该行的其余部分作为 JavaScript 注释。所以网络浏览器会忽略&lt;script&gt; 标签。不过,Visual Studio 认为所有 cshtml 文件都是 HTML。 Visual Studio 将// 读取为纯文本以发送到浏览器,但将&lt;script&gt; 标记视为JavaScript 块的开头。 &lt;script&gt; 标记之后的所有内容都被着色为 JavaScript,您应该从自动完成中获得 JavaScript 建议。 顺便说一句 - 我已经设法做到了没有“返回”部分等:i.imgur.com/yxp52fL.jpg。所以我现在不明白@return; 部分 @return; 之后的任何内容都不会发送到浏览器。 cshtml 执行到此结束。 @ 在 cshtml 视图中开始内联 C#。 return; 通常从方法或函数返回,但在这种情况下它从 cshtml 页面返回。 结束 cshtml 页面内的内联 C#。【参考方案3】:

为时已晚,但仍然很有趣,这是我的解决方案: 像这样形成你的 cshtml 调用:

<script src='@Url.Action("GetJS", "Home")'></script>

创建一个像这样生成 JS 或 CSS 的控制器方法:

public ActionResult GetJS()

     byte[] jsDATA = System.Text.ASCIIEncoding.ASCII.GetBytes(mystingJS); 
     return File(jsDATA, "text/javascript");

【讨论】:

【参考方案4】:

有一种相对较新的语言TypeScript,我认为这可能是您正在寻找的 JavaScript,而不是 CSS。 Here 是一篇让其在 ASP.NET MVC4 中工作的帖子。

【讨论】:

是的,很遗憾 TypeScript 是开箱即用的解决方案,而且还不清楚 IntelliSense 如何在那里工作。 在撰写本文时,TypeScript 开始成熟,VS 中的智能感知非常出色。虽然,我不确定这是否真的是用户要求的。

以上是关于在 ASP.NET MVC 中动态生成 Javascript、CSS的主要内容,如果未能解决你的问题,请参考以下文章

asp.net mvc 3 和动态视图生成

如何使用 jquery unobtrusive 和 Asp.Net Mvc 验证动态生成的单选按钮组?

如何使用jQuery unobtrusive和Asp.Net Mvc验证动态生成的单选按钮组?

ASP.Net MVC:具有动态列的 Jquery 数据表与 JSON 绑定

asp.net mvc 开发人员的 javascript 最佳实践

如何在 ASP.NET MVC 中使用多个表单元素