1

I'm working with asp.net mvc4, How I can read data from ViewBag, my ViewBag is a Generic List, I would like to access the data (viewbag) from javascript.

I'm passing a generic list from the controller to the view, this list helps me to load a dropdownlist up here works well. Besides loading the dropdownlist I need to access some generic list data so that when the value of the dropdownlist to update a textbox with data from the list

raranibar
  • 1,247
  • 4
  • 23
  • 44
  • hi Shyju, I'm trying to do is when the DropDownList value change value generic list is copied to a textbox – raranibar Jun 25 '13 at 19:44
  • 1
    show some code please – Shyju Jun 25 '13 at 19:46
  • Shyju, this is my code var myList = '@Html.Raw(ViewBag.Coberturas as List)'; alert(myList.cdo_descripcion); the message from alert is 'value undefiened' – raranibar Jun 25 '13 at 19:57
  • @raranibar Could you provide any feedback on my answer, please? I think that's what you were looking for. If it's not the case, leave I'll comment and I'll work on it – Andre Calil Jun 25 '13 at 20:46

5 Answers5

3

Technically you ViewBag is a dictionary that can contain a Generic List. It is only available when your page is initially rendered. Thus you can't access it directly from JavaScript. But what you can do is get the list from your ViewBag, serialize it as JSON in Razor and deserialize it in JavaScript.

public ActionResult Index(){
    //make this whatever list you want
    ViewBag.MyList = new ArrayList();
}

This sets a key in the ViewBag dictionary equal to a list of your choosing. Now, we need to serialize it so we can access it in JavaScript.

var jsonList = '@Html.Raw(Json.Convert(ViewBag.MyList))'
var jsList = JSON.parse(jsonList);

This is a lot of work to just get a list, not to mention, making dependencies in the View for Newtonsoft.Json or whatever serializer you use, and also if memory serves, it is not very efficient. Why not make a request to get the data you need from an API controller which will take care of the serialization for you, resulting in a faster initial page load?

Edit: I think what you're looking for is this. You don't need to use JavaScript to achieve what you are asking for. Leverage the power of MVC.

Community
  • 1
  • 1
pfluggs11
  • 166
  • 2
  • 9
1

One of the easiest ways to pass data back and forth from your ASP.NET code to your JS layer, is to serialize your objects and then render the serialization into the View as a JS object. Here's an example:

// helper extension method
public static string ToJSON(this object o)
{
    var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    return oSerializer.Serialize(o);
}

Inside your controller:

Viewbag.Foo = myObj.ToJSON();

Then, inside your View, you just spit out the serialized obj as literal JavaScript:

var json = @Html.Raw(Viewbag.Foo); // mix of Razor and JS here! 

When you run it, if you view source, you'll see something like this in that section of the View:

var json = {"prop1":true, "arrayItems":[{ "prop1": "dog" }, { "prop": "car" }]}
Graham
  • 3,217
  • 1
  • 27
  • 29
1

DISCLAIMER

This is an extremely straightforward, simple and non-elegant solution. However, it works =)

Consider this class:

public class Something
{
    public int Id { get; set; }
    public string PropA { get; set; }
    public string PropB { get; set; }
}

And this code on your action:

List<Something> list = new List<Something>() { 
  new Something(){ Id = 1, PropA = "1-A", PropB = "1-B "}
  , new Something(){ Id = 2, PropA = "2-A", PropB = "2-B "}
};

ViewBag.Things = list;

Finally, the view:

<select id="theSelect">
    @foreach (Something item in ViewBag.Things)
    { 
        <option value="@item.Id">@item.PropA</option>
    }
</select>
<input type="text" id="selectedPropB" readonly />
<div style="display: none;">
    @foreach (Something item in ViewBag.Things)
    { 
        <span id="propb-@item.Id">@item.PropB</span>
    }
</div>
<script type="text/javascript">
    $(function () {
        $('#theSelect').on('change', function () {
            var id = $(this).val();

            $('#selectedPropB').val($('#propb-'+id).html());
        });
    });
</script>

Notes:

  • I'd rather be using a viewmodel instead of the ViewBag, because reasons. Anyway, it's up to you
  • I'm sure you can find better solutions if you work with knockout and so on. Anyway, as I said, this works
Andre Calil
  • 7,652
  • 34
  • 41
  • Andre Calil, thanks for your answer I probe and work with their data, but the project I'm doing is much cost its implementation – raranibar Jun 25 '13 at 21:39
  • @raranibar I'm sorry, I didn't understand. Are you saying that it would be hard to implement? – Andre Calil Jun 26 '13 at 00:36
  • Andre Calil, I use to load the dropdownlist a function that returns me data from the database and to customize according to the script you sent me and takes a long time to solve my problem when there is a change in the dropdownlist to a function call (controller).ajax to update the textobox, I appreciate your concern, I will use your solution in other projects .. thank you very much – raranibar Jun 26 '13 at 20:04
  • @raranibar Ok, glad to help anyway – Andre Calil Jun 26 '13 at 20:29
1
<script type="text/javascript">
     var jsList= @Html.Raw(Json.Encode(@ViewBag.GenericList));
</script>
ecasper
  • 489
  • 1
  • 10
  • 30
0

This answer is simple and Okay

<script type="text/javascript">
     var jsList= @Html.Raw(Json.Encode(@ViewBag.GenericList));
</script>

But default .Net Json.Encode has some problem and not friendly with javascript data type (example Datetime field will get format like /Date(1245398693390)/) so I recommend to use Newtonsoft.Json.JsonConvert

<script type="text/javascript">
     var jsList= @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(@ViewBag.GenericList));
</script>
Bùi Đức Khánh
  • 3,975
  • 6
  • 27
  • 43