working section scripts not mvc from javascript asp.net-mvc razor

section - Usando Razor dentro de JavaScript



render partial view mvc 5 ajax (12)

¿Es posible o existe una solución alternativa para usar la sintaxis de Razor en JavaScript que está en una vista ( cshtml )?

Estoy tratando de agregar marcadores a un mapa de Google ... Por ejemplo, probé esto, pero obtengo un montón de errores de compilación:

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


¿Qué errores específicos estás viendo?

Algo como esto podría funcionar mejor:

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

Tenga en cuenta que necesita la etiqueta mágica <text> después del foreach para indicar que Razor debe cambiar al modo de marcado.


Acabo de escribir esta función de ayuda. Póngalo en App_Code/JS.cshtml :

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

Luego, en tu ejemplo, puedes hacer algo como esto:

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

Fíjate en cómo no pongo comillas a su alrededor. Si el título ya contiene comillas, no explotará. ¡Parece manejar los diccionarios y objetos anónimos muy bien también!


Eso funcionará bien, siempre y cuando esté en una página CSHTML y no en un archivo JavaScript externo.

Al motor de plantillas Razor no le importa lo que está generando y no distingue entre <script> u otras etiquetas.

Sin embargo, debe codificar sus cadenas para evitar ataques XSS .


Estás intentando atascar una clavija cuadrada en un agujero redondo.

Razor fue pensado como un lenguaje de plantilla que genera HTML. Es muy posible que logres que genere código JavaScript, pero no fue diseñado para eso.

Por ejemplo: ¿Qué pasa si Model.Title contiene un apóstrofe? Eso rompería tu código JavaScript, y Razor no lo escapará correctamente de manera predeterminada.

Probablemente sería más apropiado usar un generador de cadenas en una función auxiliar. Es probable que haya menos consecuencias involuntarias de ese enfoque.


Finalmente encontré la solución (* .vbhtml):

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


La siguiente solución me parece más precisa que combinar JavaScript con Razor. Mira esto: https://github.com/brooklynDev/NGon

Puede agregar casi cualquier información compleja a ViewBag.Ngon y acceder a ella en JavaScript

En el controlador:

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

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

Permite cualquier objeto CLR antiguo (POCO) que pueda ser serializado usando el JavascriptSerializer predeterminado.


Ninguna de las soluciones anteriores funcionó correctamente ... He intentado todas las formas, pero no me dio el resultado esperado ... Por fin descubrí que hay algunos errores en el código ... Y se da el código completo abajo.

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


Prefiero "<! -" "> como un" texto> "

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


También hay una opción más que @: y <text></text> .

Usando el bloque <script> sí.

Cuando necesites hacer grandes trozos de JavaScript dependiendo del código de Razor, puedes hacerlo así:

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

Las ventajas de esta manera es que no mezcla demasiado JavaScript y Razor, porque mezclarlos mucho causará problemas de legibilidad en el futuro. También los bloques de texto grandes tampoco son muy legibles.


Un simple y un buen ejemplo directo:

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

Esto crea una secuencia de comandos en su página en la ubicación donde coloca el código anterior, que se parece a lo siguiente:

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

Ahora tiene una variable de JavaScript global llamada razorUserName que puede acceder y usar en el cliente. El motor de Razor obviamente extrajo el valor de @User.Identity.Name (variable del lado del servidor) y lo puso en el código que escribe en su etiqueta de script.


Una cosa para agregar: descubrí que el compilador de sintaxis Razor (y probablemente el compilador) interpreta la posición del corchete de apertura de manera diferente:

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


Use el pseudo-elemento <text> , como se describe here , para forzar al compilador Razor a volver al modo de contenido:

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

Actualizar:

Scott Guthrie publicó recientemente acerca de @: syntax en Razor, que es un poco menos torpe que la etiqueta <text> si solo tienes una o dos líneas de código JavaScript para agregar. El siguiente enfoque probablemente sería preferible, ya que reduce el tamaño del HTML generado. (Incluso podría mover la función addMarker a un archivo JavaScript estático y en caché para reducir aún más el tamaño):

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

Se actualizó el código anterior para que la llamada a addMarker más correcta.

Para aclarar, @: que Razor vuelva al modo de texto, aunque la llamada addMarker parece mucho al código C #. Razor luego recoge la sintaxis de @item.Property para decir que debe mostrar directamente el contenido de esas propiedades.

Actualización 2

Vale la pena señalar que Ver código realmente no es un buen lugar para colocar código JavaScript. El código de JavaScript se debe colocar en un archivo .js estático, y luego debe obtener los datos que necesita de una llamada Ajax o escaneando los atributos de data- del HTML. Además de hacer posible el almacenamiento en caché de su código JavaScript, esto también evita problemas con la codificación, ya que Razor está diseñado para codificar HTML, pero no JavaScript.

Ver código

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

Código JavaScript

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