-1

I don't know if this is a basic stuff but I'm a having a hard time on populating a variable from a JSON result. I can't just find a right keyword on it.

What I want to do is populate this variable.

Js File

var opts = [
 { key: 1, label: 'High' },
 { key: 2, label: 'Normal' },
 { key: 3, label: 'Low' }
];

Layer

public IEnumerable<DropdownModel> ToLayerLevel()
    {
        List<DropdownModel> data = new List<DropdownModel>();
        using (SqlConnection con = new SqlConnection(Conn.MyConn()))
        {
            SqlCommand com = new SqlCommand("SELECT id, desc FROM PriorityLevel", con);
            con.Open();
            SqlDataReader reader = com.ExecuteReader();
            while (reader.Read())
            {
                DropdownModel value = new DropdownModel();
                value.key = reader.GetInt32(0);
                value.label = reader.GetString(1);
                data.Add(value);
            }
        }
        return data;
    }

Controller

public JsonResult ddlToLayerLevel()
    {
        DropdownLayers ddl = new DropdownLayers();
        var data = ddl.ToLayerLevel();
        return Json(data, JsonRequestBehavior.AllowGet);
    }
Yuu
  • 619
  • 3
  • 13
  • 34
  • What relationship does that json array (which is a collection of items with properties `key` and `label`) have to do with your `DropdownModel` model which has properties `ID` and `Description`? (is `key` equal to `ID` and `label` equal to `Description`) –  Nov 15 '17 at 03:11
  • 1
    And you have shown a method named `LayerLevel()` which has no parameters, but your controller code calls a method named `ToLayerLevel()` which accepts one argument –  Nov 15 '17 at 03:13
  • @StephenMuecke Yes. "`key` equal to `ID` and `label` equal to `Description`". My bad – Yuu Nov 15 '17 at 03:14
  • Then edit you question to explain that (and fix the issue with your method name/parameter) –  Nov 15 '17 at 03:15
  • @StephenMuecke I edited it. Thanks for pointing out. – Yuu Nov 15 '17 at 03:15
  • do you want to change those field names to `key` and `label` or keep them as `id` and `description`? – Neville Nazerane Nov 15 '17 at 03:16
  • are you using any js library like jquery? – Neville Nazerane Nov 15 '17 at 03:16
  • @NevilleNazerane yes. I'm currently using jquery – Yuu Nov 15 '17 at 03:17

2 Answers2

2

You can make an ajax call to the server action method where it will return the data you need

public JsonResult ddlToLayerLevel()
{
    var ddl = new DropdownLayers();
    var data = ddl.ToLayerLevel().ToList();
    return Json(data, JsonRequestBehavior.AllowGet);
}

This will return an array of items with key and label properties, in JSON format

[{"key":1,"label":"High"},{"key":2,"label":"Normal"},{"key":3,"label":"Low"}]

Now you can call this action method using ajax . Here is a sample using jQuery $.get method.

var url="/YourControllerName/ddlToLayerLevel";
$.get(url).done(function(resultArray) {
                // resultArray is an array of items.
                //  Use it inside this callback method scope
             var opts=resultArray;
             console.log(opts);
          });

To avoid 404 Not found errors, when making ajax call's from external js files, you may use the Url.Action method to generate the correct relative path in your view file(where you can execute C# methods like Url.Action) and use that in your external js file.

For example, you can do like this in your razor view file

<script>
    var myProject= myProject|| {};
    myProject.layerLevelUrl ="@Url.Action("ddlToLayerLevel","YourControllerName")";
</script>
<script src="pathToYourExternalJsFile.js"></script>

Now in your external js file you can use it like

$.get(myProject.layerLevelUrl)
 .done(function(resultArray) {
     // resultArray is an array of items. Use it inside this callback method
     var opts=resultArray;
     console.log(JSON.stringify(opts));
 });
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Perfect. Thank you for your detailed explanation and helping me again. – Yuu Nov 15 '17 at 03:34
  • I used to do something similar for the action urls but the `var myProject= myProject|| {};` is a nice trick. It would use any `myProject` variable present from a layout or partial view too. – Neville Nazerane Nov 15 '17 at 03:51
  • That is just a sample. Ideally I would use a full namespace mycompany.myproject.mymodule.xxx. Also I always wrap code inside iEFE blocks and pass these to those blocks – Shyju Nov 15 '17 at 03:54
  • @Shyju did you mean `IIFE` as mentioned [here](https://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript) ? – Shaiju T Nov 15 '17 at 05:05
  • 1
    @stom. Yes! Was typing from the phone app and did not pay much attention ;) – Shyju Nov 15 '17 at 14:21
0

Getting data using jQuery:

var opts = [];
$.getJSON("<your url here>", function(res){
    opts = res;
});

There is an alternate simplified way I use when I need to get objects created in c# directly into a js variable. It does come with pros and cons though

pros

  1. Much quicker to code rather than having to create a controller and call a js ajax function every time.
  2. Loads the entire page in one go and overall loads the data into js faster.

cons

  1. The code doesn't go into your js file but instead into a cshtml file.
  2. The information is only fetched in load time and the code can't be reused in real time when the page is still open.
  3. If you don't need the js variable on page load, not using this would speed up the initial page load speed and will load the js information later.

First I create an extension function in static class as follows:

public static IHtmlContent ToJS(this IHtmlHelper htmlHelper, object obj)
{    
    return htmlHelper.Raw(JsonConvert.SerializeObject(obj));
}

Now in any cshtml file I can define the js variable by simply using the following:

@{
    DropdownLayers ddl = new DropdownLayers();
    var data = ddl.ToLayerLevel();
}

<script>
    var opts = @Html.ToJS(data);
</script>
Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79