199

I'm pretty confused with how to mix razor and js. This is the current function I am stuck with:

<script type="text/javascript">

        var data = [];

        @foreach (var r in Model.rows)
        {
                data.push([ @r.UnixTime * 1000, @r.Value ]);
        }

If I could declare c# code with <c#></c#> and everything else was JS code -- this would be what I am after:

<script type="text/javascript">

        var data = [];

        <c#>@foreach (var r in Model.rows) {</c#>
                data.push([ <c#>@r.UnixTime</c#> * 1000, <c#>@r.Value</c#> ]);
        <c#>}</c#>

What is the best method to achieve this?

Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
Kyle Brandt
  • 26,938
  • 37
  • 124
  • 165
  • 2
    Apparently the syntax highlighting is nice and confused with my `` tags as well :-P – Kyle Brandt Apr 10 '11 at 21:47
  • 1
    Did you check the HTML output of this view? How does it look, and how you you want it to differ? – sukru Apr 10 '11 at 21:49
  • Throws up an error about `Conditional Compilation ` so I can't see the HTML -- so I believe it feels part of this is C# code. – Kyle Brandt Apr 10 '11 at 21:52
  • 1
    It seems like a JavaScript error: http://www.webdeveloper.com/forum/showthread.php?t=99780 . What is the exact error message, and where do you get it? – sukru Apr 10 '11 at 21:54
  • 2
    I think this is a case where trying to mix JS and C# so closely would be a pain to read/maintain. I'm glad the compiler disallowed you from this code. :) – Jim Bolla Apr 10 '11 at 21:56
  • @Kyle Brandt: you only need one `` element that wraps around the contents of `@foreach`. – Max Toro Apr 10 '11 at 22:04
  • Dont do this at all. Export data to JS variable array or what and then use clean javascript. – Mertuarez Apr 29 '16 at 13:34

8 Answers8

373

Use <text>:

<script type="text/javascript">

   var data = [];

   @foreach (var r in Model.rows)
   {
      <text>
            data.push([ @r.UnixTime * 1000, @r.Value ]);
      </text>
   }
</script>
Max Toro
  • 28,282
  • 11
  • 76
  • 114
  • 32
    Razor works fine in Javascript blocks when executed but I hate how the syntax highlighting gets all sorts of confused. It highlights all the Razor code as invalid Syntax because it's stuck in Javascript mode I believe. – CatDadCode Aug 10 '12 at 16:29
  • 2
    what about if this code is in a bundle?? can I write code inside of a javascript file?? – ncubica Jan 28 '13 at 05:06
  • 3
    Works perfectly until you want to check if one variable is less than another and razor goes psycho! – cbp Dec 11 '14 at 01:59
  • 1
    @ncubica if you want razor in bundle, than somethings wrong in your concept. Razor is for views, not javascript. – 100r Jul 01 '16 at 10:24
  • 2
    @ncubica This post is old, but the solution to your question is: Write a function in a JS file, render it with `Scripts.Render`, then call the function in a ` – Sinjai Jul 20 '17 at 19:26
  • @Sinjai wao. time flies, these day webpack and react all way :P, I don't even remember the reason of my question. – ncubica Jul 21 '17 at 23:25
95

Inside a code block (eg, @foreach), you need to mark the markup (or, in this case, Javascript) with @: or the <text> tag.

Inside the markup contexts, you need to surround code with code blocks (@{ ... } or @if, ...)

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
63

you also can simply use

<script type="text/javascript">

   var data = [];

   @foreach (var r in Model.rows)
   {
       @:data.push([ @r.UnixTime * 1000, @r.Value ]);
   }
</script>

note @:

Medet Tleukabiluly
  • 11,662
  • 3
  • 34
  • 69
13

Never ever mix more languages.

<script type="text/javascript">
    var data = @Json.Encode(Model); // !!!! export data !!!!

    for(var prop in data){
      console.log( prop + " "+ data[prop]);
    }

In case of problem you can also try

@Html.Raw(Json.Encode(Model));
Mertuarez
  • 901
  • 7
  • 24
  • This is great, but also, there are legitimate instances where we need to mix. But this is the solution I used since it fit perfectly. – frostymarvelous Jul 29 '16 at 11:08
  • 4
    Note that this _is_ mixing languages. You have a statement that is half-JavaScript ("var data = ") and half-Razor/C# ("@Json.Encode(Model)"). It's just a less invasive mixing, but it is no less mixing than having a Razor/C# "foreach" whose body emits generated JavaScript. :-) – Jonathan Gilbert Feb 20 '18 at 18:07
  • 3
    It returns `Uncaught SyntaxError: Unexpected token &` because the model becomes something like this `[{"Id":1,"Name":"Name}]` – Weihui Guo Feb 04 '19 at 15:33
  • This is the best and simplest solution. Definitely need to feed the encoded JSON through Html.Raw() to get rid of the `"` entities. – Mike Finch Nov 05 '20 at 20:58
2

A non conventional method to separate javascript from the view, but still use razor in it is to make a Scripts.cshtml file and place your mixed javascript/razor there.

Index.cshtml

<div id="Result">
</div>

<button id="btnLoad">Click me</button>

@section scripts
{
    @Html.Partial("Scripts")
}

Scripts.cshtml

<script type="text/javascript">
    var url = "@Url.Action("Index", "Home")";

    $(document).ready(function() {
        $("#btnLoad").click(function() {
            $.ajax({
                type: "POST",
                url: url ,
                data: {someParameter: "some value"},
                contentType: "application/json; charset=utf-8",
                dataType: "json",

                success: function(msg) {
                    $("#Result").text(msg.d);
                }
            });
        });
    });
</script>
Joel Wiklund
  • 1,697
  • 2
  • 18
  • 24
2

This is my way to hack Razor and use Javascript without freaking out Intellisense.

Obviously you should use <text> but with an "expedient": double braces before.

This is what happens if a single brace is used:

enter image description here

This is what happen if a couple of braces are used:

enter image description here

Now constants and variable have been recognized. It's better, but not good! There is still the "less than" symbol that confuses intellisense making it think that following is the name of a tag. The "less than" sign is signaled as error and from here there are parsing errors as "console.log" shows. You need to add something that quiets intellisense and doesn't get returned in the final JS code at compile time.

Solution: use this comment after "less than": /*>*/

This is the result

enter image description here

It's quite strange to see, but it works as it should.

Dharman
  • 30,962
  • 25
  • 85
  • 135
tedebus
  • 978
  • 13
  • 20
0

you can use the <text> tag for both cshtml code with javascript

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
-3

Wrap your Razor code in @{ } when inside JS script and be aware of using just @ Sometimes it doesn't work:

function hideSurveyReminder() {
       @Session["_isSurveyPassed"] = true;
    }

This will produce

function hideSurveyReminder() {
       False = true;
    }

in browser =(