在视图(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>
答案 0 :(得分:596)
使用<text>
伪元素(如here所述)强制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>
<强>更新强>
关于Razor中@:
语法的 Scott Guthrie recently posted,如果你只需要添加一行或两行JavaScript代码,它就会比<text>
标签略显笨重。以下方法可能更可取,因为它减少了生成的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>
更新了上述代码,使对addMarker
的调用更加正确。
澄清一下,@:
迫使Razor回到文本模式,即使addMarker
调用看起来很像C#代码。然后Razor选择@item.Property
语法来说它应该直接输出这些属性的内容。
值得注意的是,View代码确实不是放置JavaScript代码的好地方。 JavaScript代码应放在静态.js
文件中,然后它应该从Ajax调用或扫描HTML中的data-
属性获取所需的数据。除了可以缓存JavaScript代码之外,这也避免了编码问题,因为Razor旨在编码HTML,而不是JavaScript。
@foreach(var item in Model)
{
<div data-marker="@Json.Encode(item)"></div>
}
$('[data-marker]').each(function() {
var markerData = $(this).data('marker');
addMarker(markerData.Latitude, markerData.Longitude,
markerData.Description, markerData.Title);
});
答案 1 :(得分:38)
我刚写了这个辅助函数。把它放在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);
注意我怎么不在它周围加上引号。如果标题已包含引号,则不会爆炸。似乎也很好地处理字典和匿名对象!
答案 2 :(得分:22)
你试图把一个方形的钉子塞进圆孔里。
Razor旨在用作生成HTML的模板语言。您很可能会生成JavaScript代码,但它不是为此设计的。
例如:如果Model.Title
包含撇号怎么办?这会破坏您的JavaScript代码,默认情况下Razor无法正确转义它。
在辅助函数中使用String生成器可能更合适。这种方法可能会产生更少的意外后果。
答案 3 :(得分: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>
请注意,您需要<text>
后面的神奇foreach
标记,表示Razor应切换到标记模式。
答案 4 :(得分:11)
只要它在CSHTML页面而不是外部JavaScript文件中,那就可以正常工作。
Razor模板引擎不关心它输出的内容,也不区分<script>
或其他标签。
但是,您需要对字符串进行编码以防止XSS攻击。
答案 5 :(得分:10)
我更喜欢“&lt;! - ”“ - &gt;”比如“text&gt;”
<script type="text/javascript">
//some javascript here
@foreach (var item in itens)
{
<!--
var title = @(item.name)
...
-->
</script>
答案 6 :(得分:8)
要添加的一件事 - 我发现Razor语法高亮显示器(可能还有编译器)以不同方式解释左括号的位置:
<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>
答案 7 :(得分: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>
这会在页面中放置代码的位置创建一个脚本,如下所示:
<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
的全局JavaScript变量,您可以在客户端上访问和使用它。 Razor引擎显然从@User.Identity.Name
(服务器端变量)中提取了值,并将其放入写入脚本标记的代码中。
答案 8 :(得分: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();
}
}
在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>
允许使用默认JavascriptSerializer
序列化的任何plain old CLR objects(POCO)。
答案 9 :(得分:5)
除了@:和<text></text>
之外,还有一个选项。
使用<script>
阻止本身。
当您需要根据Razor代码执行大量JavaScript时,您可以这样做:
@if(Utils.FeatureEnabled("Feature")) {
<script>
// If this feature is enabled
</script>
}
<script>
// Other JavaScript code
</script>
这种方式的优点是它不会混淆JavaScript和Razor太多,因为混合它们会最终导致可读性问题。大文本块也不是很易读。
答案 10 :(得分:4)
以前的解决方案都没有正常工作......我已经尝试了所有方法,但它没有给我预期的结果......最后我发现代码中有一些错误......而且完整代码如下。
<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>
答案 11 :(得分:4)
我终于找到了解决方案(* .vbhtml):
function razorsyntax() {
/* Double */
@(MvcHtmlString.Create("var szam =" & mydoublevariable & ";"))
alert(szam);
/* String */
var str = '@stringvariable';
alert(str);
}