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 1612 posts 7258 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.

Please Sign in or register to post replies

Write your reply to:

Draft