469 Stimmen

Verwendung von Razor in JavaScript

Ist es möglich oder gibt es einen Workaround, um die Razor-Syntax innerhalb von JavaScript zu verwenden, das sich in einer Ansicht befindet ( cshtml )?

Ich versuche, Marker zu einer Google-Karte hinzuzufügen... Zum Beispiel habe ich dies versucht, aber ich bekomme eine Menge Kompilierungsfehler:

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

676voto

StriplingWarrior Punkte 141402

Verwenden Sie die <text> Pseudo-Element, wie beschrieben aquí um den Razor-Compiler zurück in den Inhaltsmodus zu zwingen:

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

Aktualisierung:

Scott Guthrie veröffentlichte kürzlich über @: Syntax in Razor, die etwas weniger klobig ist als die <text> Tag, wenn Sie nur eine oder zwei Zeilen JavaScript-Code hinzufügen möchten. Der folgende Ansatz ist wahrscheinlich vorzuziehen, weil er die Größe des generierten HTML reduziert. (Sie könnten die Funktion addMarker sogar in eine statische, zwischengespeicherte JavaScript-Datei verschieben, um die Größe weiter zu reduzieren):

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

Der obige Code wurde aktualisiert, um den Aufruf an addMarker richtiger.

Zur Klarstellung: Die @: zwingt Razor zurück in den Textmodus, auch wenn addMarker Aufruf sieht dem C#-Code sehr ähnlich. Razor nimmt dann den @item.Property Syntax, um anzugeben, dass der Inhalt dieser Eigenschaften direkt ausgegeben werden soll.

Aktualisierung 2

Es ist erwähnenswert, dass der Ansichtscode wirklich kein guter Platz für JavaScript-Code ist. JavaScript-Code sollte in einem statischen .js Datei und sollte dann die benötigten Daten entweder über einen Ajax-Aufruf oder durch Scannen von data- Attribute aus dem HTML. Dies ermöglicht nicht nur die Zwischenspeicherung Ihres JavaScript-Codes, sondern vermeidet auch Probleme mit der Kodierung, da Razor für die Kodierung von HTML, aber nicht von JavaScript ausgelegt ist.

Code anzeigen

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

JavaScript-Code

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

40voto

mpen Punkte 253762

Ich habe gerade diese Hilfsfunktion geschrieben. Setzen Sie es in App_Code/JS.cshtml :

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

In Ihrem Beispiel können Sie dann etwa so vorgehen:

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

Beachten Sie, dass ich sie nicht in Anführungszeichen gesetzt habe. Wenn der Titel bereits Anführungszeichen enthält, wird er nicht explodieren. Scheint auch mit Wörterbüchern und anonymen Objekten gut zurechtzukommen!

24voto

Adam Lassek Punkte 34556

Du versuchst, einen eckigen Pflock in ein rundes Loch zu stopfen.

Razor war als HTML-generierende Template-Sprache gedacht. Sie können es sehr wohl dazu bringen, JavaScript-Code zu erzeugen, aber dafür wurde es nicht entwickelt.

Zum Beispiel: Was wäre, wenn Model.Title ein Hochkomma enthält? Das würde Ihren JavaScript-Code kaputt machen, und Razor bricht ihn standardmäßig nicht korrekt aus.

Es wäre wahrscheinlich sinnvoller, einen String-Generator in einer Hilfsfunktion zu verwenden. Dieser Ansatz wird wahrscheinlich weniger unbeabsichtigte Folgen haben.

19voto

marcind Punkte 52454

Welche spezifischen Fehler treten auf?

Etwas in dieser Art könnte besser funktionieren:

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

Beachten Sie, dass Sie die magische <text> Tag nach dem foreach um anzuzeigen, dass Razor in den Auszeichnungsmodus wechseln soll.

13voto

SLaks Punkte 832502

Das funktioniert gut, solange es in einer CSHTML-Seite und nicht in einer externen JavaScript-Datei ist.

Die Razor Template Engine kümmert sich nicht darum, was sie ausgibt und unterscheidet nicht zwischen <script> oder andere Tags.

Sie müssen Ihre Zeichenketten jedoch kodieren, um zu verhindern, dass XSS Angriffe.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X