17

I am using ASP.Net MVC 3 Razor view engine.

I have a requirement to generate some JavaScript code in my View based on a value in my View Model. The value I need to use is a boolean, for this example lets call it IsSet.

So what I want to do is create a JavaScript boolean based on this value that I can use in the script later on.

Keep in mind that for all below examples I have this bit of code at the top of my view...

@{ string IsSet = Model.IsSet  ? "true" : "false"; }

NOTE: All examples below are JavaScript.

First attempt...

var IsSet = @(IsSet);

... this actually works, the problem is it breaks the auto-formatting (CTRL + E, D) in VS 2010 due to badly formatted JavaScript - as you might expect, and this is not acceptable.

Second attempt...

var IsSet = "@(IsSet)";

...I know, JavaScript is clever, it will auto-parse my string when needed. Ooops, forgot it is a string type and anything other than empty evaluates to true.

Third attempt...

var IsSet = Boolean("@(IsSet)");

....surely this will work... nope, convert non-empty string to true again (bad parser!)

Fourth attempt...

var IsSet = "@(IsSet)" === "true";

Finally something that works, but it doesn't look great to me.

I will use this if need be but ultimately my question is: Is there a better way to handle this kind of situation? Perhaps, the unwanted behaviour in my first attempt is just something that Microsoft may have overlooked?

If anybody has a nice and tidy fifth attempt for me, that would be good.

The important thing for me is that the auto-formatting in VS 2010 does not break

Thanks

2
  • I'd have to agree with your first attempt - that looks like the most natural to me, as you're not stringifying and then casting something that was already a Boolean in the first place! I've used that technique a lot throughout my Razor / JS code and it seems to work fine, and I haven't seen any problems with auto-formatting, but I do use ReSharper so maybe that fixes it up automatically! Commented Dec 19, 2011 at 11:29
  • I use ReSharper and I still run into the auto-formatting issue, so I'm not sure that's why you're not hitting formatting issues. The auto-formatting and capitalization issue occurs when you have Pascal-cased Razor variables appearing in places where the formatter would enforce lowercase naming, such as HTML tag names or JS code (predominantly camelCase; in particular, the formatter kicks in when auto-indentation occurs...So Chris, I've got a hunch you might have had a different scenario? Commented Mar 23, 2015 at 18:46

9 Answers 9

14

I just wrestled with the same issue for about an hour. My final solution was equivalent to the following.

var IsSet = @(Model.IsSet.ToString().ToLower()); // Inside JavaScript block

This requires no additional code.

Sign up to request clarification or add additional context in comments.

2 Comments

This will break in the same way the very first attempt did. Intellisense will not recognise that something was written for the variable initialisation and show a red squiggly line at the semicolon.
Perfect in MVC 4. tks
11

None of the versions shown so far (both in the question and answers) is something that I would use. Here's how I would do it:

@model MyViewModel
<script type="text/javascript">
    var isSet = @Html.Raw(Json.Encode(Model.IsSet));

    // TODO: use the isSet javascript variable here as a standard boolean value
</script>

or if you needed other properties of your view model to be manipulated with javascript you could JSON encode the entire model:

@model MyViewModel
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));

    if (model.IsSet) {
        alert(model.FooBar);
    }
</script>

3 Comments

Nice alternative, but this still breaks the auto-formatting for JavaScript. Also, as it stands I get an error "Conditional compilation is turned off"... added brackets solves this part of the problem... @(Html.Raw(Json.Encode(Model.IsSet)));
@musefan, Intellisense in Razor, especially when mixed with javascript sucks badly. It is something that I have stopped worrying long time ago. Hopefully Microsoft will fix it in some future version. It emits some warnings that shouldn't be emitted. Personally I focus on writing correct code that is not vulnerable to XSS injection attacks, ... and which I know will properly work at runtime as it correctly encodes everything. The fact that VS gives me warnings on some perfectly valid code is something that the designers of VS should be blamed for, not yourself as the author of this code.
This is a nice alternative. Although it breaks the auto-formatting that would only be a problem on the one line right at the start, with no other server-side code mixed into the JavaScript.
7

Version 1 is the only one of those that I'd vote for even if they all worked, because it's the most human-readable. Unfortunately I don't have VS at home so I can't try it out to see what the auto-formatting issue is, but if at all possible I'd want to ignore the issue and go ahead and use that version given that there's nothing actually wrong with the code - it is just VS that is confused. (Are you saying VS is trying to interpret the whole thing as JS and thus finding it invalid?)

But if you want some other options:

Fifth attempt...

@{ string IsSet = Model.IsSet  ? "true" : ""; }

var isSet = !!"@(IsSet)";
// OR
var isSet = Boolean("@(IsSet)");

Coerce the string value into a boolean with the old double-not-operator trick - as you already pointed out both "true" and "false" would become true, but this problem goes away if you use "true" and "" (empty string) - so you can use Boolean() as per your "third attempt".

Sixth attempt...

@{ string IsSet = Model.IsSet  ? "true" : "false"; }

// helper function at the top of your page:
function bool(strVal) {
   return strVal === "true";
}

// variable declaration
var isSet = bool("@(IsSet)");

OK, so you end up with a fairly pointless function at the top of your page, but it keeps the actual variable declarations reasonably tidy and if debugging client side you'll see bool("false") or bool("true").

Seventh attempt...

I don't like the extra step of creating the server-side string IsSet = Model.IsSet ? "true" : "false"; in advance. I don't know Razor syntax, but can you say something along the lines of:

var isSet = !!"@(Model.IsSet ? "true" : "")";
// OR, better:
var isSet = !!"@(rzrBool(Model.IsSet))";
// where rzrBool() is a server-side helper function (that you would create)
// which returns "true" or ""

I would expect all of my "attempts" to work, but again I think your "first attempt" is the best option.

3 Comments

By the way, are the parentheses really necessary everywhere you've said @(IsSet), or can you just say @IsSet? If the latter is OK that would make every variation neater.
Firstly, the problem with auto-formatting is it just doesn't do anything when you have invalid JavaScript. The same would apply if you missed a closing bracket from a function call etc. Second, you answers all look workable, except you seventh would probably require a using ' to wrap the whole string to avoid issues with containing quotes, also this option looks nasty. I do agree the first is the best, but auto-formatting is too important to give up. I could go for the bool function, as I have other views that do similar things.
I suspect my "5b" is the best option for you. Doesn't require any additional functions (client- or server-side), and is just like your third attempt once you modify the server-side code to return "true" or empty string instead of "true" or "false". (Regarding my 7a, yes, you'd need to use single-quotes on the outside to make VS happy though again it should run as-is.)
1

How about:

@Ajax.ToJson(Model.IsSet)

1 Comment

What is @Ajax.ToJson()? It doesn't show up in my intellisense, or in Google
1
var isSet = /true/i.test('@Model.IsSet');
  • Single line
  • Handles the case difference between .Net and JavaScript
  • Works with auto-formatting (Visual Studio, and Visual Studio with Resharper)
  • Reasonably idiomatic if you are familiar with JavaScript regexes
  • Fairly resilient to logic errors; it should do as intended or throw a JavaScript error (or possibly a Razor compilation error).

Comments

0

How about:

@Model.IsSet.ToString().ToLower()

8 Comments

No good. I assume you mean to use this direct in the JavaScript block? If you mean to replace the first line of my C# razor code, then it wont make a difference there either.
it prints out False for me.... maybe if you add .ToLower() for false, var something = @Model.IsSet.ToString().ToLower();
Yeah, it would work. But like my first attempt, it breaks the auto-formatting in VS 2010
or if you make IsSet a string in the model, and format it when assigning value to it.
I am making it a string at the top of my code. Teh auto-format doesnt like the randon @ character in the JavaScript block. That is the problem
|
0
var isSet= @((bool)Model.IsSet?"true":"false");

1 Comment

this is a bad answer. First there is no point in casting Model.IsSet to bool because it is bool already. Second, if you mean to do this in JavaScript you still have the same issue as my first attempt (auto-formatting breaks)
0

Here is what I use, inside a javascript block:

var someValue;
@{ var someValue= "someValue= " + Model.SomeValue+ ";"; }
@someValue

Comments

0

I know this is an old question, but none of the answers are particularly elegant.

The simplest solution in these situations is simply to append +0 to your conditional. This implicitly converts the bool to an int, but since the result is 0 or 1 it's immediately converted back again by the if statement. Example:

// The space is optional
if (@IsSet +0) {
    // Do stuff
}

Assigning a boolean value to a variable could be achieved as follows:

// Note the double (not triple) equals, which performs type conversion
var isSet = @IsSet+0 == true;

The code works, you get no red squiggly lines, and the Visual Studio formatter is happy.

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.