Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Joseph 14 posts 93 karma points
    Sep 02, 2021 @ 19:36
    Joseph
    0

    How do I populate a dropdown with data from a controller?

    Umbraco newbie here, sorry if this is a dumb question.

    My goal: I have a partial view with a dropdown in it, I want to get JSON data from an api to populate it.

    Right now I have a controller that calls the api, and returns the data in a List<>. However I can't call the controller from the view, and I suspect that isn't a great plan anyway. I would like to use the same controller that returns the partial view, but I don't think it goes through a controller, so I created a new one.

    This is the method in my controller:

        [System.Web.Http.HttpGet]
        [Route("GetDropdownData")]
        public List<ReportDropdown> Index()
        {
            List<ReportDropdown> result = new List<ReportDropdown>();
            string json;
    
            using (WebClient wc = new WebClient())
            {
                json = wc.DownloadString("http://apiurl....");
            }
    
            result = JsonConvert.DeserializeObject<List<ReportDropdown>>(json);
    
            return result;
    
        }
    

    This creates my List<> correctly. However I don't know how to get this data to my view. As near as I can tell, the partial view doesn't go through a controller before it is displayed, so I can't put it into viewdata which would be my first choice.

    Any guidence?

  • Nik 1625 posts 7295 karma points MVP 7x c-trib
    Sep 02, 2021 @ 22:04
    Nik
    0

    Hi Joseph,

    Can you elaborate a bit more on how your Partial view is called as you don't appear to mention that in your original post?

    Thanks

    Nik

  • Thomas Kassos 54 posts 265 karma points
    Oct 01, 2021 @ 20:36
    Thomas Kassos
    0

    I am not sure If I understand correctly what you are trying to achieve but here is one approach.

    Create a Controller which will be return a PartialView with the populated dropdown from the API

    public class TestController :SurfaceController
    {
        [ChildActionOnly]
        public ActionResult Index()
        {
            List<ReportDropdown> result = new List<ReportDropdown>();
            string json;
    
            using (WebClient wc = new WebClient())
            {
                json = wc.DownloadString("http://apiurl....");
            }
    
            result = JsonConvert.DeserializeObject<List<ReportDropdown>>(json);
    
            return PartialView("~/Views/Partials/{YourView}", result);
        }
    }
    

    Create the PartialView that the controller will return. Will look like that

        @inherits UmbracoViewPage<List<ReportDropdown>>
    
        <label for="myDropDown">My DropDown</label>
        <select name="myDropDown" id="myDropDown">
           <option disabled="disabled" value="">Please Select...</option>
           @foreach (var item in Model)
           {
               <option value="@item">@item</option>
           }
       </select>
    

    And in your page call that controller to get the populated dropdown

    @Html.Action("Index","Test")
    

    and you will get only a dropdown with the api values

  • Joseph 14 posts 93 karma points
    Oct 01, 2021 @ 20:38
    Joseph
    0

    What do you mean "The actual page that is connected with the doctype"?

  • Thomas Kassos 54 posts 265 karma points
    Oct 01, 2021 @ 22:28
    Thomas Kassos
    0

    Hi Joseph,

    Forget that, I correct it in my answer. Also, I fixed and some bits in my code.

    Once you have create the controller and the PartialView you can use that

    @Html.Action("Index","Test")
    

    in any view to get the dropdown

  • Joseph 14 posts 93 karma points
    Oct 04, 2021 @ 14:42
    Joseph
    0

    Thank you for this, I am trying to get Html.Action working but get an error that there is no route that matches. Here is what I am trying to do:

    Controller:

    public class TestController : BaseController
    {
        [Route("TestView")]
        public ActionResult TestView()
        {
            string modelString = "Test String";
            return View("~/Views/Test/TestView.cshtml", modelString);
        }
    }
    

    The HTML view I am trying to pull in is as basic as it gets:

    @model string
    
    @Model
    

    And this is where I am trying to call the controller:

    @Html.Action("Test","TestView")
    

    Any idea why this is not working? If I can figure out how to get data from the controller like this it would be amazing.

  • Thomas Kassos 54 posts 265 karma points
    Oct 04, 2021 @ 14:53
    Thomas Kassos
    100

    Hi,

    you can copy my example and it will probably work.

    In your code sample I can see 4-5 issues.

    • In the controller: remove the [Route("TestView")] attribute
    • In the controller: you need to return a PartialView (see my code). And place your html you want to return inside ~/Views/Partials/Test/TestView.cshtml

    • In the controller: Does the BaseController inherit for the SurfaceController ? if not replace it with the SurfaceController

    • In the partial view replace

    @model string

    with

    @inherits UmbracoViewPage<string>
    

    maybe its the same thing I am not sure but just in case do that I know it works

    • and in the view its @Html.Action("{actionResultName}", "{controllername}") so in your case @Html.Action("TestView", "Test")

    Optionally but good to have use the [ChildActionOnly], see my example. With this one your controller will be more secure and will be called only from your c# code. For example You will not be able to call that controller with ajax

  • Joseph 14 posts 93 karma points
    Oct 04, 2021 @ 15:08
    Joseph
    0

    Made the changes you suggested, getting the same result. To be clear it is erroring on Html.Action, and never reaches my test controller. Here is a summary of what I changed:

    Switched the Html.Action to use the method name first and the controller name second.

    Moved the view into the partials folder.

    In the partial view, Instead of using a model I just typed in "This is working!" to simplify the test.

    Removed the route attribute in the test controller.

    Any idea what I can check next?

  • Joseph 14 posts 93 karma points
    Oct 04, 2021 @ 15:10
    Joseph
    0

    In response to your edit, inheriting from SurfaceController did the trick, thank you!

  • Thomas Kassos 54 posts 265 karma points
    Oct 04, 2021 @ 15:11
    Thomas Kassos
    0

    Nice!! we got it working!

  • Joseph 14 posts 93 karma points
    Oct 04, 2021 @ 15:16
    Joseph
    0

    Looks like our BaseController inherits from RenderMvcController. What is the difference between RenderMvcController and SurfaceController?

  • Thomas Kassos 54 posts 265 karma points
    Oct 04, 2021 @ 15:27
    Thomas Kassos
    0

    you can read more here

    https://our.umbraco.com/documentation/Implementation/Controllers/

    In sort with a RenderMvcController you could overwrite the default route of Umbraco and return a page through your custom controller. Or return all the pages through that controller. https://our.umbraco.com/Documentation/Implementation/Default-Routing/Controller-Selection/index-v8

    https://our.umbraco.com/Documentation/Reference/Routing/custom-controllers-v8

    The surface controllers are auto-routed, they return only partial views. They are good for things like this one or for a form submission. I think the surface controllers are the most common to use.

    Also that [Route] attributes I don't think they will work the Surface controller, maybe with the UmbracoApiController if I am wrong.

    you can read more about routing here https://our.umbraco.com/Documentation/Reference/Routing/custom-routes-v8

    https://our.umbraco.com/Documentation/Reference/Routing/surface-controllers-v8

    General speaking if you search into Umbraco Documentation, you will find what you need with a good example.

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies