在JavaScript中使用Razor

在视图( 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> 

使用<text>伪元素,如此处所述,强制Razor编译器回到内容模式:

 <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> 

更新:

Scott Guthrie最近在Razor上发布了关于@:语法的内容,如果你只添加了一行或两行JavaScript代码,它比<text>标签稍微笨拙。 下面的方法可能会更好,因为它减less了生成的HTML的大小。 (你甚至可以将addMarker函数移动到一个静态的,caching的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> 

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

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

更新2

值得注意的是,查看代码真的不是放置JavaScript代码的好地方。 JavaScript代码应该放在一个静态的.js文件中,然后它应该从Ajax调用或通过扫描HTML中的data-属性来获取它所需要的data- 。 除了可以cachingJavaScript代码,这也可以避免编码问题,因为Razor被devise为编码HTML,而不是JavaScript。

查看代码

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

JavaScript代码

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

我只写了这个帮助函数。 把它放在App_Code/JS.cshtml

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

然后在你的例子中,你可以做这样的事情:

 var title = @JS.Encode(Model.Title); 

注意我怎么不把它引用。 如果标题已经包含引号,则不会爆炸。 似乎很好地处理字典和匿名对象!

你正在试图把一个方形的钉子塞在一个圆孔里。

Razor的目的是作为一个HTML生成模板语言。 您可能很好地生成JavaScript代码,但它不是为此devise的。

例如:如果Model.Title包含一个撇号呢? 这会破坏你的JavaScript代码,并且Razor默认不会正确地转义它。

在辅助函数中使用String生成器可能更合适。 这种方法可能会导致意想不到的后果。

你看到了什么具体的错误?

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

 <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> 

请注意,在foreach之后需要神奇的<text>标签来指示Razor应该切换到标记模式。

这将工作得很好,只要它在一个CSHTML页面,而不是一个外部的JavaScript文件。

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

但是,您需要对string进行编码以防止XSS攻击。

我更喜欢“<! – ”“ – >”像“文本”“

 <script type="text/javascript"> //some javascript here @foreach (var item in itens) { <!-- var title = @(item.name) ... --> </script> 

有一件事要补充 – 我发现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> 

一个简单而直接的例子:

 <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> 

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

 <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> 

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

还有一个比@和<text></text>更多的选项。

使用<script>块本身。

当你需要根据Razor代码来完成大块的JavaScript时,你可以这样做:

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

这种方式的优点是它不会混合使用JavaScript和Razor,因为混合它们会导致可读性问题。 同样大的文本块也不是很可读。

下面的解决scheme似乎比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(); } } 

在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> 

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

以前的解决scheme没有任何工作正常…我已经尝试了所有的方法,但它没有给我预期的结果…最后我发现代码中有一些错误…并给出完整的代码下面。

 <script type="text/javascript"> var map = new google.maps.Map(document.getElementById('map'), { zoom: 10, center: new google.maps.LatLng(23.00, 90.00), mapTypeId: google.maps.MapTypeId.ROADMAP }); @foreach (var item in Model) { <text> var markerlatLng = new google.maps.LatLng(@(item.LATITUDE), @(item.LONGITUDE)); var title = '@(item.EMP_ID)'; var description = '@(item.TIME)'; var contentString = '<h3>' + "Employee " +title+ " was here at "+description+ '</h3>' + '<p>'+" "+ '</p>' var infowindow = new google.maps.InfoWindow({ // content: contentString }); var marker = new google.maps.Marker({ position: markerlatLng, title: title, map: map, draggable: false, content: contentString }); google.maps.event.addListener(marker, 'click', (function (marker) { return function () { infowindow.setContent(marker.content); infowindow.open(map, marker); } })(marker)); </text> } </script> 

我终于find了解决scheme(* .vbhtml):

 function razorsyntax() { /* Double */ @(MvcHtmlString.Create("var szam =" & mydoublevariable & ";")) alert(szam); /* String */ var str = '@stringvariable'; alert(str); }