जावास्क्रिप्ट के भीतर रेजर का उपयोग करना


435

क्या यह संभव है या जावास्क्रिप्ट के भीतर रेजर सिंटैक्स का उपयोग करने के लिए वर्कअराउंड है जो एक दृश्य ( cshtml) में है?

मैं एक 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
आपको @:सिंटैक्स के बारे में मेरे अपडेट में दिलचस्पी हो सकती है ।
स्ट्रिपिंगवर्यर

@ इस तरह से करने पर विचार करते हुए, कम से कम डेटा को एक अलग स्क्रिप्ट टैग में रखा जाता है जो बस कुछ JSON को परिभाषित करता है जो तब JS में उपयोग किया जाता है। बैक-एंड-कपल्ड जेएस सामने के छोर पर कई अवसरों पर मेरे लिए एक विरासत PITA रहा है। अगर आपको नहीं करना है तो कोड के साथ कोड न लिखें। इसके बजाय डेटा को बंद करें।
एरिक रेपेन

जवाबों:


637

<text>छद्म तत्व का उपयोग करें , जैसा कि यहां वर्णित है , रेजर कंपाइलर को सामग्री मोड में वापस लाने के लिए मजबूर करने के लिए:

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

अपडेट करें:

स्कॉट गुथ्री ने हाल ही@: में रेजर में वाक्य रचना के बारे में पोस्ट किया है , जो <text>टैग की तुलना में थोड़ा कम क्लंकी है यदि आपके पास जोड़ने के लिए जावास्क्रिप्ट कोड की सिर्फ एक या दो लाइनें हैं। निम्नलिखित दृष्टिकोण शायद बेहतर होगा, क्योंकि यह उत्पन्न HTML के आकार को कम करता है। (आप भी आकार को कम करने के लिए addMarker फ़ंक्शन को स्थिर, कैश्ड जावास्क्रिप्ट फ़ाइल में स्थानांतरित कर सकते हैं):

<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अधिक सही बनाने के लिए अपडेट किया गया ।

स्पष्ट करने के लिए, @:रेजर पाठ मोड में वापस आ जाता है, भले ही addMarkerकॉल सी # कोड की तरह दिखता है। उस्तरा तो उठाता है@item.Property सिंटैक्स को यह कहने के लिए चुना कि यह सीधे उन गुणों की सामग्री का उत्पादन करना चाहिए।

अपडेट २

यह ध्यान देने योग्य है कि जावास्क्रिप्ट कोड डालने के लिए व्यू कोड वास्तव में अच्छी जगह नहीं है। जावास्क्रिप्ट कोड को एक स्थिर .jsफ़ाइल में रखा जाना चाहिए , और फिर उसे वह डेटा प्राप्त करना चाहिए जो उसे या तो अजाक्स कॉल से चाहिए या data-HTML से विशेषताओं को स्कैन करके । अपने जावास्क्रिप्ट कोड को कैश करना संभव बनाने के अलावा, यह एन्कोडिंग के साथ मुद्दों से भी बचता है, क्योंकि रेजर को HTML के लिए एन्कोड करने के लिए डिज़ाइन किया गया है, लेकिन जावास्क्रिप्ट नहीं।

कोड देखें

@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
मैं आपके अद्यतन उदाहरण को नहीं समझता। Addmarker फ़ंक्शन सही है?
एनवीएम

2
@ एनवीएम: एक ही जावास्क्रिप्ट कोड को कई बार आउटपुट करने के बजाय, मैं एक एकल जावास्क्रिप्ट फ़ंक्शन (जिसे कैश्ड .js फ़ाइल में रखा जा सकता है) बनाने का सुझाव देता हूं, और उस फ़ंक्शन में कई कॉल आउटपुट करता हूं। मुझे पता नहीं है कि क्या फ़ंक्शन सही है: मैं इसे केवल ओपी कोड पर आधारित कर रहा था।
StriplingWarrior

1
फॉरवर्ड में '@ मॉडल.लीटिट्यूड' क्यों। आइटम क्यों नहीं।
NVM

5
आपके C # वैरिएबल को बच जाने की जरूरत है। यदि @item.Titleएक भी उद्धरण होता है तो यह कोड फट जाएगा।
एमपीएन

7
@ मर्क: अच्छा अवलोकन। वास्तव में, मैं आम तौर पर अपने स्वयं के कोड में जावास्क्रिप्ट और रेजर को संयोजित नहीं करता हूं: मैं एचटीएमएल को data-विशेषताओं के साथ उत्पन्न करने के लिए रेजर का उपयोग करना पसंद करता हूं , और फिर डोम से इस जानकारी को चमकाने के लिए स्थिर, विनीत जावास्क्रिप्ट का उपयोग करता हूं । लेकिन यह पूरी चर्चा सवाल के दायरे से परे थी।
स्ट्रिपिंगवर्यर

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 की टिप्पणी शानदार है। एक तरह से आप जावास्क्रिप्ट ब्लॉक में सर्वर साइड मॉडल को डिसेर्बलाइज करते हैं।
नेटफेड

24

आप एक गोल छेद में एक वर्ग खूंटे को जाम करने की कोशिश कर रहे हैं।

रेज़र का उद्देश्य एचटीएमएल जेनरेट करने वाली टेम्प्लेट लैंग्वेज थी। आप जावास्क्रिप्ट कोड उत्पन्न करने के लिए इसे बहुत अच्छी तरह से प्राप्त कर सकते हैं, लेकिन इसे इसके लिए डिज़ाइन नहीं किया गया था।

उदाहरण के लिए: क्या अगर Model.Title एपोस्ट्रोफ होता है ? यह आपके जावास्क्रिप्ट कोड को तोड़ देगा, और रेजर डिफ़ॉल्ट रूप से इसे सही ढंग से बच नहीं पाएगा।

संभवतः सहायक फ़ंक्शन में स्ट्रिंग जनरेटर का उपयोग करना अधिक उपयुक्त होगा। उस दृष्टिकोण के कम अनपेक्षित परिणाम होने की संभावना होगी।


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>

ध्यान दें कि आपको इंगित करने के <text>बाद जादुई टैग की आवश्यकता foreachहै कि रेजर को मार्कअप मोड में स्विच करना चाहिए।


1
iterate मॉडल (foreach द्वारा) और @ Model.Latidue चिह्नित किया? समारोह का कार्य क्या है? मुझे लगता है कि कुछ याद किया। यह @ Item.Latitude etc हो सकता है
Nuri YILMAZ

12

यह तब तक ठीक काम करेगा, जब तक कि यह एक CSHTML पेज में है और बाहरी जावास्क्रिप्ट फ़ाइल नहीं है।

रेजर टेम्पलेट इंजन परवाह नहीं करता है कि यह आउटपुट क्या है और इसके बीच अंतर नहीं करता है <script> अन्य टैग्स के ।

हालाँकि, आपको XSS हमलों को रोकने के लिए अपने तारों को एनकोड करना होगा ।


2
मैंने अपना प्रश्न अपडेट कर लिया है, यह मेरे लिए काम नहीं कर सकता है-विचार गलत है? धन्यवाद
राकोस

3
@ क्राकोल: आपको अपने तार से बचने की जरूरत है। कॉलHTML.Raw(Server.JavaScriptStringEncode(...))
एसएलकेएस

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.क्या आपको यकीन है कि एओबूट है? stackoverflow.com/questions/33666065/…
HMR

2
@HMR: जब मैंने यह उत्तर लिखा था, तब यह सुविधा मौजूद नहीं थी।
एसएलए

11

मैं "पाठ" की तरह "<! -" "->" पसंद करता हूं

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

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

</script>

यह अजीब तरह से एक समाधान है जो मेरे लिए काम करता है, क्योंकि मुझे जिस पाठ को शामिल करने की आवश्यकता थी, उसमें कुछ सीमांकक थे जो रेजर को @:और <text>विधियों के साथ पसंद नहीं आया
बडज़ीज़

8

जोड़ने के लिए एक चीज - मैंने पाया कि रेजर सिंटैक्स हाइलाइटर (और शायद कंपाइलर) उद्घाटन ब्रैकेट की स्थिति को अलग तरीके से व्याख्या करता है:

<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आप क्लाइंट पर एक्सेस और उपयोग कर सकते हैं। रेजर इंजन ने स्पष्ट रूप से @User.Identity.Name(सर्वर-साइड चर) से मान निकाला है और इसे उस कोड में डाल दिया है जो आपके स्क्रिप्ट टैग पर लिखता है।


6

निम्नलिखित समाधान मेरे लिए जावास्क्रिप्ट के साथ रेजर के साथ संयोजन की तुलना में अधिक सटीक लगता है। इसकी जांच करें: https://github.com/brooklynDev/NGon

आप ViewBag.Nagon में लगभग किसी भी जटिल डेटा को जोड़ सकते हैं और इसे जावास्क्रिप्ट में एक्सेस कर सकते हैं

नियंत्रक में:

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>

यह किसी भी सादे पुराने सीएलआर ऑब्जेक्ट (POCO) को अनुमति देता है जिसे डिफ़ॉल्ट का उपयोग करके क्रमबद्ध किया जा सकता है JavascriptSerializer


5

@ और: की तुलना में एक और विकल्प भी है <text></text>

<script>स्वयं ब्लॉक का उपयोग करना ।

जब आपको रेजर कोड के आधार पर जावास्क्रिप्ट के बड़े हिस्से करने की आवश्यकता होती है, तो आप इसे इस तरह से कर सकते हैं:

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

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

इस तरह से पेशेवरों का कहना है कि यह जावास्क्रिप्ट और रेजर को बहुत ज्यादा नहीं मिलाता है, क्योंकि उन्हें मिश्रण करने से अंततः पठनीयता के मुद्दे पैदा होंगे। इसके अलावा बड़े पाठ ब्लॉक या तो बहुत पठनीय नहीं हैं।


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);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.