1

Given the need to extract data from a viewdata into a javascript key/value object:

var stuff = {
    something : [@someVar.Prop2, @someVar.Prop3, etc]
};

I want to make the key have the "name" of someVar.Prop1 so that:

var stuff = {
    @someVar.Prop1 : [@someVar.Prop2, @someVar.Prop3, etc]
};

Yet when I use the form in the second code block above, I get a Expected identifier, string or number error at the colon:

@someVar.Prop1 : [@someVar.Prop2, etc]
---------------X (x marks the spot)

How do I need to format the razor code so that it knows what I'm trying to say?

user4593252
  • 3,496
  • 6
  • 29
  • 55
  • best way i know how to do it is to surround with `'`s, parsing the values you need if necessary. Ex: `var stuff = { something : [ '@myVal', parseInt('@myVal2') ] }` – DLeh Jan 27 '15 at 21:03
  • heh, although your quotes and I think your intent was on the wrong side of the assignment, it looks like it fixed it? Pop it up as an answer and as soon as I see it working, I'll mark it as *the* answer. – user4593252 Jan 27 '15 at 21:05

3 Answers3

2

You should definitely not be trying to build your JSON piece by piece in your Razor view. That can go wrong very easily.

To expand on @DLeh's answer, what you can do is build a dictionary of the values you want, serialize that into JSON right in your Razor view, and assign that to your variable as shown here:

@{
    // Assume that someVar is provided from somewhere else; 
    // this is just for demonstration
    var someVar = new { Prop1 = "My Prop", Prop2 = "Prop Value", Prop3 = 7 };
}

@{
    var obj = new Dictionary<string, object>
    {
        {someVar.Prop1, new object[] { someVar.Prop2, someVar.Prop3 } }
    };
}
<script>
    var stuff = @Html.Raw(Json.Encode(obj));
</script>

Rendered output:

<script>
    var stuff = {"My Prop":["Prop Value",7]};
</script>
Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • I am actually doing this in my code but not by using Json directly. I will rewrite the code using your example because it effectively does the same thing but in a cleaner way. It also avoids the issue I originally posed. I'll make yours at the answer – user4593252 Jan 28 '15 at 14:52
1

You can surround razor expressions in quotes ' or " to have them output into a javascript block. If you need the type to be preserved properly, you can use methods like parseInt() or parseFloat() to do so.

Example:

var stuff = {
    value1 : '@val1',
    value2 : [ parseInt('@val2'), parseInt('@val3') ]
};

If you need to left side of the assignment to be variable, you will probably need to build a json string and then parse that into the object. Something like this, my quotes might be off.

var stuffJson = '{"@value1" : "@val1", "@value2" : "[ @val2, @val3 ]" }';
var stuff = JSON.parse(stuffJson);

If you're doing this a lot, you might want to consider using the Json() method in your controller to help you build these more easily. You could build a dictionary of key / value and have that output json:

public virtual ActionResult GetStuff()
{
    string value1 = "key1",
        value2 = "key2",
        val1 = "str1",
        val2 = "str2",
        val3 = "str3";
    var dict = new Dictionary<string, object>
    {
        { value1, val1},
        { value2, new List<string> { val2, val3} },
    };

    return Json(dict, JsonRequestBehavior.AllowGet);
}

Output:

{"key1":"str1","key2":["str2","str3"]}
DLeh
  • 23,806
  • 16
  • 84
  • 128
  • 1
    The first approaches will break if any of the values contain HTML special characters. Using proper JSON serialization is definitely the way to go when feasible. – JLRishe Jan 27 '15 at 21:16
  • yes, I would imagine that the `Json()` method would know how to properly escape those, so that's another reason to recommend using that instead of the other examples. – DLeh Jan 27 '15 at 21:17
  • 1
    On the other hand, your `GetStuff()` method does not accomplish OP's objective (the property names will be hardcoded to `value1` and `value2`). I'm not sure what's the cleanest way around that. Perhaps `dynamic`? – JLRishe Jan 27 '15 at 21:22
  • oh yeah, i guess you're right. might have to build the Json manually one way or the other. – DLeh Jan 27 '15 at 21:23
  • Yeah, looks like serializing a `Dictionary` is a good approach. – JLRishe Jan 27 '15 at 22:00
  • Unfortunately, I have to pass this data in through viewdata/bag because of various silly reasons that I can't change (base architecture but to be clear, I end up getting the data as an ObjectsSet). So a server side approach to shaping the data isn't quite going to work, especially when two lines of code client-side deals with it. However, your use of json is the way that it needs to go. I have a working version for now and will clean it up once I get it a little more wrapped up. – user4593252 Jan 28 '15 at 14:54
-1

The answer is to ignore Visual Studio's complaint of the problem as the code runs and throws no error:

@country.CountryCode: ['@someVar.Prop1', '@someVar.Prop2', etc],
user4593252
  • 3,496
  • 6
  • 29
  • 55
  • Can anyone explain why this has a negative score? It answers my own question and is factually correct. The other answers, which are good examples of better ways to do some of what I want here, don't exactly answer the question I originally posed which was "How to mark up the razor code so as not to show an error in VS." This answer does. – user4593252 Jan 28 '15 at 14:49