在JavaScript中使用Razor

rak*_*los 419 javascript asp.net-mvc razor

在view(cshtml)中的JavaScript中使用Razor语法是否可行或有解决方法?

我正在尝试将标记添加到Google地图中...例如,我试过这个,但是我收到了大量的编译错误:

<script type="text/javascript">

    // Some JavaScript code here to display map, etc.

    // Now add markers
    @foreach (var item in Model) {

        var markerlatLng = new google.maps.LatLng(@(Model.Latitude), @(Model.Longitude));
        var title = '@(Model.Title)';
        var description = '@(Model.Description)';
        var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'

        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position: latLng,
            title: title,
            map: map,
            draggable: false
        });

        google.maps.event.addListener(marker, 'click', function () {
            infowindow.open(map, marker);
        });
    }
</script>
Run Code Online (Sandbox Code Playgroud)

Str*_*ior 618

使用<text>伪元素,如所描述这里,迫使剃刀编译器返回到内容模式:

<script type="text/javascript">

    // Some JavaScript code here to display map, etc.


    // Now add markers
    @foreach (var item in Model) {
        <text>
            var markerlatLng = new google.maps.LatLng(@(Model.Latitude), @(Model.Longitude));
            var title = '@(Model.Title)';
            var description = '@(Model.Description)';
            var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'

            var infowindow = new google.maps.InfoWindow({
                content: contentString
            });

            var marker = new google.maps.Marker({
                position: latLng,
                title: title,
                map: map,
                draggable: false
            });

            google.maps.event.addListener(marker, 'click', function () {
                infowindow.open(map, marker);
            });
        </text>
    }
</script>
Run Code Online (Sandbox Code Playgroud)

更新:

Scott Guthrie最近发布了关于@:Razor的语法,<text>如果你只需添加一行或两行JavaScript代码,它就会比标签略显笨重.以下方法可能更可取,因为它减少了生成的HTML的大小.(您甚至可以将addMarker函数移动到静态缓存的JavaScript文件中以进一步减小大小):

<script type="text/javascript">

    // Some JavaScript code here to display map, etc.
    ...
    // Declare addMarker function
    function addMarker(latitude, longitude, title, description, map)
    {
        var latLng = new google.maps.LatLng(latitude, longitude);
        var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>';

        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position: latLng,
            title: title,
            map: map,
            draggable: false
        });

        google.maps.event.addListener(marker, 'click', function () {
            infowindow.open(map, marker);
        });
    }

    // Now add markers
    @foreach (var item in Model) {
        @:addMarker(@item.Latitude, @item.Longitude, '@item.Title', '@item.Description', map);
    }
</script>
Run Code Online (Sandbox Code Playgroud)

更新了上面的代码,使调用addMarker更加正确.

为了澄清,@:Razor 的力量回到文本模式,即使addMarker调用看起来很像C#代码.然后Razor选择@item.Property语法来说它应该直接输出这些属性的内容.

更新2

值得注意的是,View代码确实不是放置JavaScript代码的好地方.JavaScript代码应放在静态.js文件中,然后它应该从Ajax调用或扫描data-HTML中的属性获取所需的数据.除了可以缓存JavaScript代码之外,这还避免了编码问题,因为Razor旨在编码HTML,而不是JavaScript.

查看代码

@foreach(var item in Model)
{
    <div data-marker="@Json.Encode(item)"></div>
}
Run Code Online (Sandbox Code Playgroud)

JavaScript代码

$('[data-marker]').each(function() {
    var markerData = $(this).data('marker');
    addMarker(markerData.Latitude, markerData.Longitude,
              markerData.Description, markerData.Title);
});
Run Code Online (Sandbox Code Playgroud)

  • @Mark:很好的观察.事实上,我通常不会在我自己的代码中结合使用javascript和Razor _at all_:我更喜欢使用Razor生成带有`data -`属性的HTML,然后使用静态的,不引人注目的javascript从DOM中收集这些信息.但整个讨论超出了问题的范围. (7认同)
  • 您的C#变量需要转义.如果`@ item.Title`包含单引号,则此代码将爆炸. (5认同)
  • 我不明白你更新的例子.添加标记功能是否正确? (3认同)
  • @NVM:我不是多次输出相同的javascript代码,而是建议创建一个单独的javascript函数(可以保存在缓存的.js文件中),并输出对该函数的多个调用.我不知道函数是否正确:我只是基于OP的代码. (2认同)

mpe*_*pen 40

我刚写了这个辅助函数.把它放进去App_Code/JS.cshtml:

@using System.Web.Script.Serialization
@helper Encode(object obj)
{
    @(new HtmlString(new JavaScriptSerializer().Serialize(obj)));
}
Run Code Online (Sandbox Code Playgroud)

然后在您的示例中,您可以执行以下操作:

var title = @JS.Encode(Model.Title);
Run Code Online (Sandbox Code Playgroud)

注意我怎么不在它周围加上引号.如果标题已包含引号,则不会爆炸.似乎也很好地处理字典和匿名对象!

  • 如果您尝试在视图中对对象进行编码,则无需创建帮助程序代码.我们一直使用这个`@ Html.Raw(Json.Encode(Model))` (18认同)
  • 你能扩展你的答案PJH吗?如果您只是编码"模型",如何指定标题? (2认同)
  • 此外,当我使用Model.Title尝试这种方法时,我在编码的javascript周围得到一些额外的引号.即使我将它连接到别的东西,我也无法摆脱引号.这些引用成为你的js的一部分. (2认同)

Ada*_*sek 22

你试图把一个方形的钉子塞进圆孔里.

Razor旨在用作生成HTML的模板语言.您很可能会生成JavaScript代码,但它不是为此而设计的.

例如:如果Model.Title包含撇号怎么办?这会破坏您的JavaScript代码,默认情况下Razor无法正确转义它.

在辅助函数中使用String生成器可能更合适.这种方法可能会产生更少的意外后果.


mar*_*ind 16

您看到了哪些具体错误?

像这样的东西可以更好地工作:

<script type="text/javascript">

//now add markers
 @foreach (var item in Model) {
    <text>
      var markerlatLng = new google.maps.LatLng(@Model.Latitude, @Model.Longitude);
      var title = '@(Model.Title)';
      var description = '@(Model.Description)';
      var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
    </text>
}
</script>
Run Code Online (Sandbox Code Playgroud)

请注意,<text>foreach指示Razor应切换到标记模式后,您需要使用魔法标记.


SLa*_*aks 11

只要它在CSHTML页面而不是外部JavaScript文件中,这样就可以正常工作.

Razor模板引擎不关心它输出的内容,也不区分它们<script>或其他标签.

但是,您需要对字符串进行编码以防止XSS攻击.

  • @raklos:你需要逃避你的弦乐.调用`HTML.Raw(Server.JavaScriptStringEncode(...))` (3认同)
  • 我已经更新了我的问题,这对我不起作用 - 任何想法都错了吗?谢谢 (2认同)
  • @HMR:当我写这个答案时,那个功能不存在. (2认同)

Fer*_* JS 10

我更喜欢"<! - "" - >"喜欢"文字>"

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

@foreach (var item in itens)
{                 
<!--  
   var title = @(item.name)
    ...
-->

</script>
Run Code Online (Sandbox Code Playgroud)


And*_*ndy 8

有一点要补充 - 我发现Razor语法hilighter(可能还有编译器)以不同的方式解释了开括号的位置:

<script type="text/javascript">
    var somevar = new Array();

    @foreach (var item in items)
    {  // <----  placed on a separate line, NOT WORKING, HILIGHTS SYNTAX ERRORS
        <text>
        </text>
    }

    @foreach (var item in items) {  // <----  placed on the same line, WORKING !!!
        <text>
        </text>
    }
</script>
Run Code Online (Sandbox Code Playgroud)


rad*_*vus 6

一个简单而好的直截了当的例子:

<script>
    // This gets the username from the Razor engine and puts it
    // in JavaScript to create a variable I can access from the
    // client side.
    //
    // It's an odd workaraound, but it works.
    @{
        var outScript = "var razorUserName = " + "\"" + @User.Identity.Name + "\"";
    }
    @MvcHtmlString.Create(outScript);
</script>
Run Code Online (Sandbox Code Playgroud)

这会在页面中放置代码的位置创建一个脚本,如下所示:

<script>
    // This gets the username from the Razor engine and puts it
    // in JavaScript to create a variable I can access from
    // client side.
    //
    // It's an odd workaraound, but it works.

    var razorUserName = "daylight";
</script>
Run Code Online (Sandbox Code Playgroud)

现在,您有一个名为的全局JavaScript变量razorUserName,您可以在客户端上访问和使用它.Razor引擎显然从@User.Identity.Name(服务器端变量)中提取了值,并将其放入写入脚本标记的代码中.


Ice*_*urn 6

以下解决方案似乎比将JavaScript与Razor结合起来更准确.看看这个:https: //github.com/brooklynDev/NGon

您可以将几乎任何复杂数据添加到ViewBag.Ngon并在JavaScript中访问它

在控制器中:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
        ViewBag.NGon.Person = person;
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

在JavaScript中:

<script type="text/javascript">
    $(function () {
        $("#button").click(function () {
            var person = ngon.Person;
            var div = $("#output");
            div.html('');
            div.append("FirstName: " + person.FirstName);
            div.append(", LastName: " + person.LastName);
            div.append(", Age: " + person.Age);
        });
    });
</script>
Run Code Online (Sandbox Code Playgroud)

它允许任何可以使用默认值序列化的普通旧CLR对象(POCO)JavascriptSerializer.


Tuu*_*oos 5

还有一个选项比@:和<text></text>.

使用<script>块本身.

当您需要根据Razor代码执行大量JavaScript时,您可以这样做:

@if(Utils.FeatureEnabled("Feature")) {
    <script>
        // If this feature is enabled
    </script>
}

<script>
    // Other JavaScript code
</script>
Run Code Online (Sandbox Code Playgroud)

这种方式的优点是它不会混淆JavaScript和Razor太多,因为混合它们会最终导致可读性问题.大文本块也不是很易读.