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.
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
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
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.
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.
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:
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?
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
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
Create the PartialView that the controller will return. Will look like that
And in your page call that controller to get the populated dropdown
and you will get only a dropdown with the api values
What do you mean "The actual page that is connected with the doctype"?
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
in any view to get the dropdown
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:
The HTML view I am trying to pull in is as basic as it gets:
And this is where I am trying to call the controller:
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.
Hi,
you can copy my example and it will probably work.
In your code sample I can see 4-5 issues.
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
@model string
with
maybe its the same thing I am not sure but just in case do that I know it works
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
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?
In response to your edit, inheriting from SurfaceController did the trick, thank you!
Nice!! we got it working!
Looks like our BaseController inherits from RenderMvcController. What is the difference between RenderMvcController and SurfaceController?
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.
is working on a reply...