JavaScript 내에서 Razor 사용


435

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

3
@:구문 에 관한 내 업데이트에 관심이있을 수 있습니다 .
StriplingWarrior

@ 이런 식으로 작업을 고려하는 사람이라면 적어도 데이터를 JS에 사용되는 JSON을 정의하는 별도의 스크립트 태그에 넣습니다. 프론트 엔드의 백엔드 결합 JS는 여러 경우에있어 레거시 PITA였습니다. 필요하지 않은 경우 코드로 코드를 작성하지 마십시오. 대신 데이터를 전달하십시오.
Erik Reppen

답변:


637

여기<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의 구문에 대해 게시했습니다<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>

addMarker보다 정확한 호출을 위해 위의 코드를 업데이트했습니다 .

명확히하기 위해 @:Razor는 addMarker호출이 C # 코드와 비슷하게 보이지만 텍스트 모드로 되돌립니다 . 그런 다음 Razor는 @item.Property구문을 선택하여 해당 속성의 내용을 직접 출력해야한다고 말합니다.

업데이트 2

View 코드는 실제로 JavaScript 코드를 넣기에 좋은 장소가 아니라는 점에 주목할 가치가 있습니다. JavaScript 코드는 정적 .js파일에 저장 한 다음 Ajax 호출에서 또는 data-HTML에서 속성을 스캔하여 필요한 데이터를 가져와야 합니다. Razor는 JavaScript가 아닌 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);
});

3
업데이트 된 예를 이해하지 못합니다. 애드 마커 기능이 올바 릅니까?
NVM

2
@NVM : 동일한 자바 스크립트 코드를 여러 번 출력하는 대신 단일 자바 스크립트 함수 (캐싱 된 .js 파일에 보관 할 수 있음)를 만들고 해당 함수에 대한 여러 호출을 출력하는 것이 좋습니다. 함수가 올바른지 전혀 모르겠습니다. 방금 OP 코드를 기반으로했습니다.
StriplingWarrior

1
foreach에서 '@ Model.Latitude'가 필요한 이유 왜 아이템이 아닌가?
NVM

5
C # 변수를 이스케이프해야합니다. @item.Title작은 따옴표가 포함되어 있으면 이 코드가 폭발합니다.
mpen

7
@ 마크 : 좋은 관찰. 사실, 나는 일반적으로 내 코드 에서 javascript와 Razor 를 전혀 결합하지 않습니다 . Razor를 사용하여 data-속성이있는 HTML을 생성 한 다음 정적이며 눈에 거슬리지 않는 자바 스크립트를 사용하여 DOM 에서이 정보를 수집 하는 것을 선호합니다 . 그러나 그 전체 토론은 문제의 범위를 벗어났습니다.
StriplingWarrior

39

방금이 도우미 함수를 작성했습니다. 그것을 넣어 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);

인용 부호를 넣지 않은 방법에 주목하십시오. 제목에 이미 따옴표가 포함되어 있으면 폭발하지 않습니다. 사전과 익명 객체도 훌륭하게 처리하는 것 같습니다!


19
뷰에서 객체를 인코딩하려는 경우 도우미 코드를 만들 필요가 없으며 이미 존재합니다. 우리는 이것을 항상 사용합니다@Html.Raw(Json.Encode(Model))
PJH

2
답 PJH를 확장 할 수 있습니까? "모델"만 인코딩하는 경우 제목을 어떻게 지정합니까?
obesechicken13

2
또한 Model.Title을 사용 하여이 접근법을 시도했을 때 인코딩 된 자바 스크립트에 대해 추가 인용문을 얻습니다. 따옴표를 다른 것으로 연결해도 따옴표를 제거 할 수 없습니다. 그 인용문은 당신의 js의 일부가됩니다.
obesechicken13

1
PJH의 의견은 훌륭합니다. 서버 측 모델을 자바 스크립트 블록으로 역 직렬화하는 방법입니다.
netfed

24

둥근 구멍에 사각형 못을 끼 우려 고합니다.

Razor는 HTML 생성 템플릿 언어로 고안되었습니다. JavaScript 코드를 생성하는 것이 좋을 수도 있지만 그렇게 설계되지 않았습니다.

예를 들어 : Model.Title아포스트로피 가 포함되어 있으면 어떻게 됩니까? 그러면 JavaScript 코드가 손상되고 Razor는 기본적으로 올바르게 이스케이프하지 않습니다.

도우미 함수에서 문자열 생성기를 사용하는 것이 더 적절할 것입니다. 이 접근 방식의 의도하지 않은 결과는 줄어들 것입니다.


17

어떤 특정 오류가 표시됩니까?

이와 같은 것이 더 잘 작동 할 수 있습니다.

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

Razor가 마크 업 모드로 전환해야 함을 나타 내기 위해 <text>뒤에 매직 태그 가 필요 foreach합니다.


1
모델을 foreach로 반복하고 @ Model.Latidue로 표시 하시겠습니까? 반복 기능은 무엇입니까? 나는 뭔가를 놓친 것 같아요. @ item.Latitude 등이 될 수 있습니다
Nuri YILMAZ

12

외부 JavaScript 파일이 아닌 CSHTML 페이지에있는 한 정상적으로 작동합니다.

Razor 템플릿 엔진은 출력되는 내용에 신경 쓰지 않으며 <script>다른 태그 나 다른 태그를 구별하지 않습니다 .

그러나 XSS 공격 을 방지하려면 문자열을 인코딩해야합니다 .


2
내 질문을 업데이트했는데 저에게 효과가 없습니다. 어떤 아이디어가 잘못 되었나요? 감사합니다
raklos

3
@raklos : 당신은 당신의 문자열을 탈출해야합니다. 전화HTML.Raw(Server.JavaScriptStringEncode(...))
SLaks

1
HTML.Raw(HttpUtility.JavaScriptStringEncode(...))- 서버 속성에는 현재이 방법이 없습니다. HttpUtility 가 수행합니다.
it3xl

1
The Razor template engine doesn't care what it's outputting and does not differentiate between <script> or other tags.당신은 확실히 aobut입니까? stackoverflow.com/questions/33666065/…
HMR

2
@ HMR :이 답변을 쓸 때 해당 기능이 존재하지 않았습니다.
SLaks

11

"text!"와 같이 "<!-" "->"를 선호합니다.

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

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

</script>

내가 포함해야 할 텍스트에 Razor가 좋아하지 않았던 일부 구분 기호 @:<text>메소드가 있었기 때문에 이것은 이상하게도 나를 위해 일한 솔루션입니다.
BuddyZ

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>

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(서버 측 변수) 에서 값을 추출 하여 스크립트 태그에 쓰는 코드에 넣었습니다.


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();
    }
}

자바 스크립트에서 :

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

default를 사용하여 직렬화 할 수있는 일반 오래된 CLR 객체 (POCO)를 허용합니다 JavascriptSerializer.


5

@ :보다 하나 이상의 옵션이 있습니다. <text></text> 있습니다.

사용 <script>블록 자체를 합니다.

Razor 코드에 따라 큰 JavaScript 청크를 수행해야하는 경우 다음과 같이 수행 할 수 있습니다.

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

<script>
    // Other JavaScript code
</script>

이 방법의 장점은 JavaScript와 Razor를 너무 많이 섞지 않는다는 것입니다. 많이 섞으면 결국 가독성 문제가 발생할 수 있기 때문입니다. 또한 큰 텍스트 블록은 읽기가 쉽지 않습니다.


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>

4

마침내 해결책 (* .vbhtml)을 찾았습니다.

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

    /* String */
    var str = '@stringvariable';
    alert(str);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.