208

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?

7
  • 2
    Apparently the syntax highlighting is nice and confused with my <c#> tags as well :-P Commented Apr 10, 2011 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? Commented Apr 10, 2011 at 21:49
  • 1
    It seems like a JavaScript error: webdeveloper.com/forum/showthread.php?t=99780 . What is the exact error message, and where do you get it? Commented Apr 10, 2011 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. :) Commented Apr 10, 2011 at 21:56
  • 1
    Dont do this at all. Export data to JS variable array or what and then use clean javascript. Commented Apr 29, 2016 at 13:34

10 Answers 10

381

Use <text>:

<script type="text/javascript">

   var data = [];

   @foreach (var r in Model.rows)
   {
      <text>
            data.push([ @r.UnixTime * 1000, @r.Value ]);
      </text>
   }
</script>
Sign up to request clarification or add additional context in comments.

7 Comments

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.
what about if this code is in a bundle?? can I write code inside of a javascript file??
Works perfectly until you want to check if one variable is less than another and razor goes psycho!
@ncubica if you want razor in bundle, than somethings wrong in your concept. Razor is for views, not javascript.
@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 <script> tag. Not exactly graceful, but it works for most (read: simple) use cases.
|
96

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, ...)

2 Comments

Why do you say "mark the markup", this wouldn't be an issue if the content was, in fact, markup.
@Max: Even though it doesn't look like markup, it is markup. (As opposed to server-side code)
62

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

Comments

12

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

4 Comments

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.
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. :-)
It returns Uncaught SyntaxError: Unexpected token & because the model becomes something like this [{&quot;Id&quot;:1,&quot;Name&quot;:&quot;Name}]
This is the best and simplest solution. Definitely need to feed the encoded JSON through Html.Raw() to get rid of the &quot; entities.
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.

Comments

1

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>

1 Comment

if i need this aproach : var action = "Index"; var url = "@Url.Action(action, "Home")";
0

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

2 Comments

"<text>" tag is missing the above answer
use backticks or ctrl + k after selecting code to format it
0

Don't do this. The current top accepted answer has a security vulnerability if the content of @r.Value would happen to have JavaScript code formatted in a way that would stop JavaScript expression.

You have to transmit data some other way. For example, you can create invisible DOM nodes and set data-* attributes on them.

Comments

0

If you are working with lists or objects, @Html.Raw is not available in .Net 9. In the Blazor SSR, you can use JsonSerializer and then parse your values using Json.Parse.

const times = JSON.parse("@(JsonSerializer.Serialize(MyList.Select(c => c.Time)))");

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.