Populate Dropdown in View from another Controller - model-view-controller

I am trying to populate a dropdown from another Controller. I have DeviceController that has a #Html.DropDownList that get populated. Originally I have the code that populates the DropDown in the controller. Now I am trying to move it to a Controller designated for dropdowns. So I have the code to populate the dropdown in one location instead of the same code in multiple Controllers. The dropdown loads correctly when I have it in the original controller however when I move it the DropDown controller I receive the following error There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'DropDownDeviceType'.
The code for my view -
#Html.DropDownList("DropDownDeviceType", null, htmlAttributes: new { #class = "form-control" })
From my DropDownController (If I have this code in my DeviceController it works as intended)
public void PopulateDevciceType(object selectDeviceType = null)
{
string voidInd = "N";
var deviceType = db.DeviceTypes
.Where(x => x.VoidInd == voidInd)
.OrderBy(x => x.DeviceType1);
//ViewData["DropDownDeviceType"] = new SelectList(deviceType, "DeviceTypeID", "DeviceType1", selectDeviceType);
ViewBag.DropDownDeviceType = new SelectList(deviceType, "DeviceTypeID", "DeviceType1", selectDeviceType);
}
In my DeviceController
//Populate dropdowns
DropDownController dropDown = new DropDownController();
dropDown.PopulateDevciceType(model.DeviceTypeID);

I understand your desire to farm out certain tasks to dedicated classes. However, I think you are overthinking this a little bit.
I'm not 100% sure what that error is actually telling you in terms of your code, but it seems like you've probably got some wonky view returns because your setting the ViewBag information within a different controller than the one that returns the view. Am I understanding that part of it correctly?
Instead of creating another controller class, create a static function somewhere that handles the list creations and ONLY the list creations. When it creates a list, have it return it.
Then, whenever you need a list to be populated, do this in the relevant controller method:
ViewBag.DropDownDeviceType= *wherever-your-static-method-is*.PopulateDeviceType(model.DeviceTypeID);

Related

Is it possible to send Model data from a View to a Controller that is not the Controller for that View?

I could not find the similar question yet, so I decided to ask it here.
I relatively new to MVC and may have some incorrect wording in my question, and I'm just wondering if that is possible to do it at all?
Usually, we are dealing with ModelViewController coupling and we return the View from a Controller with Models/Json as parameters to the returning View, so we can bind the Model to the View
I'm just wondering if we have a ViewA, ViewB ControllerA,ControllerB and a ModelA, is that possible to have a #Url.Action/Link or Ajax method to send the ModelA from the ViewA to an Action Method of a ControllerB, so, the data stored in the ModelA can be displayed in the ViewB when it is returned from the ControllerB?
I do not have any code yet and just want to know if that is possible and if so, what would be the right approach to achieve something like that?
You could do something like this:
Controller B:
public IActionResult ControllerB(ModelA data)
{
return View(data);
}
View A:
#foreach (var data in Model)
{
<li>#Html.ActionLink(#data.ModelAProperty, "ControllerB", "ControllerBFileName", new { id = data.Sys.Id })</li>
}
View B:
#model YourModel.Models.ModelA
<div>
<h3>#Model.ModelAProperty</h3>
<p>#Model.ModelAOtherProperty</p>
</div>
This should work I believe. I did this with a previous project but it was a slightly different set up, but I believe I have modified it correctly to fit your needs. Basically you are passing the data to the controller with the first view, and then using that controller to pass the data to the next view.

EditorFor parameters in Action MVC3

Having a bit of trouble figuring something out.
I've got an Action:
public ActionResult FareTypeSelector(SearchTypes searchType, SearchSource searchSource)
{
IFareTypeOptionsRepository fareTypeOptionRespoitory = new FareTypeOptionsRepository();
FareTypeOptions fareTypeOptions = fareTypeOptionRespoitory.GetFareTypeOptions(searchSource, searchType, _authentication.UserLoggedIn.CallCentreUser, _authentication.UserLoggedIn.AgencyProfile.BranchCode);
return View();
}
I've created an 'Editor', i.e. a file in EditorTemplates called FareTypeSelector.cshtml.
I want to bind my editor to a property of the model of the page that contains the editor. But I also want to pass some parameters into my action, i.e. (SearchTypes searchType, SearchSource searchSource). The idea being that the data displayed in the editor is based on this information passed in. Now I can't quite figure out if:
Is this possible?
whats the markup needed in the main view to render
this, pass the parameters and bind the resulting selected value into the main model?
Ta in advance
EditorTemplates are used for Data items from your model, not Action methods. They're using only in your view to render a specific model (or member of a model)

how to retrieve value of dropdown selection when form is not been submitted yet

I have following code
#using (Html.BeginForm())
{
#Html.DropDownListFor(m => m.IDs, new SelectList(Model. IDs), Model.SelectedID)
}
So user selection from this combo bind to SelectedID property of the model. My understanding is that this binding happen only when form is submitted. Let’s say from the same page, I need to do an AJAX call but at this point ) Model.SelectedID does not provide any value because form hasn’t been submitted yet (although user has selected something from drop down). Any ideas how to best deal with this situation?
You can use javascript.
var selectedValue = $("#IDs").val();
bind a change event to your DD
$("#DDL_ID").change(function(){
var currVal = $(this).val();
//do ajax
});
As others have pointed you would get this value with javascript on the change of the drop down list.
I wanted to point out however, that your understanding of the overload you are using for the drop down list is incorrect. This overload will display a default option box label.
For example you could prompt the users to select select something from the list:
#Html.DropDownListFor(m => m.IDs, new SelectList(Model. IDs), "Select Something...")
If you were to post the form in your example as is, you can see the selected item come across in the form. If your view model is setup in such a fashion the model binder would take over and bind this value to your "SelectedID" property.
[HttpPost]
public string DropDown(FormCollection form)
{
var selectedItem = form["IDs"];
return selectedItem;
}

Pre-populate Create View

After selecting an accountholder I want to prepopulate my Order Create View with the properties of the selected accountholder.
My Controller Action so far:
[HttpPost]
public ActionResult Create(FormCollection values)
{
var accountHolder = from a in unitOfWork.AccountHolderRepository.Get(includeProperties: "AccountHolder")
where a.CustSName == values["Name"]
select a;
foreach (var a in accountHolder)
{
ViewBag.CustFName = a.CustFName;
ViewBag.CustSName = values["Name"];
ViewBag.CustPhone = a.CustPhone;
ViewBag.CustEmail = a.CustEmail;
}
return RedirectToAction("Create", "Order");
}
Not sure if I understand correctly what are you trying to accomplish here. I'm assuming :
Displaying Empty Create form
User provides value for AccountHolder (automatic submit happens?)
You return pre-populated form
Final Create step to preserve values to database
Am I right ?
If so, instantiate the model / viewmodel you're using in your create form (you're using strongly typed view right ?) and return it like this :
return View(yourobject); //Assuming the first view returned by GET request to Create action has all the properties in place
however that should happen only if the values are missing, right. so you might want to add some more logic to your controller to verify if pre-popullation or db.Save() is required.
As you're calling RedirectToAction to the Order controller, I assume you are now in the Create method of the accountholderController?
What's your question exactly? Without specifics, I can't give you much help.
Some notes though:
Try to search for the accountholder based on its ID in the database rather than the name. You are now trusting your enduser to enter the accountholder name exactly as it is entered in the database (same case, same punctuation). ID's are more precise and require less effort to get right.
Why use the Post-Create method if all you want to do is select an accountholder from a list and then open a Create view? It would be much wiser to have a dropdownlist containing all accountholders on your main page (or wherever you want to put it). something along the lines of
<select name="accountholderID">
<option value:"ID_of_accountholder">Name_of_accountholder</option>
...
</select>
Add a button next to that. Once an accountholder is selected and the button is clicked, call your (Get, not Post) Create method in the OrderController. Pass the accountholderID as a parameter. Your Create methoud should be something like:
public ActionResult Create(string accountholderID)
{
int ID = Convert.ToInt32(accountholderID);
ViewData["Accountholder"] = database.tbl_Accountholders.SingleorDefault(x=> x.Id == ID);
...
And in your Create View just access the values of your accountholder like so:
<% var accountholder = (accountholdertype)ViewData["Accountholder"]; %>
<span> Name is <%: accountholder.Name %> </span>
I think that should get you where you want to be :-)

DropDown for Edit() [Razor]View, Pre-Loaded with Data from Model

I have the dropdowns in my Create() View working perfect.
But in the Edit() View I can't get the Data that was submited during the Create() to show up in DropDowns with the Value enterened upon Create()
I just have textboxs in place at the moment And would really like to have Data Represented in a dropdown for easy selection.
Here is one example:
Create() View - One dropdown is for EmployeeTypes, and stores selected to EmployeeTypeId
Now How do I get that to show up in the Edit() View as the same dropdown, but with Value of EmployeeId already selected?
I have a EmployeeViewModel for the Create() View
But I am just passing the model directly into the Edit() View
Should I create some kind of Employee "partial class" for the Edit() View? to handle the IEnumerable Lists?
and set:
var employeeTypes = context.EmployeeTypes.Select(et => new SelectListItem
{
Value = et.EmployeeTypeId.ToString(),
Text = et.Type.ToString()
});
Or should I pass them in as ViewData?
If so how to do you pass a List in as ViewData and get it to display as an #Html.DropDownList with the Value passed in from the #Model as the defualt value?
I ended up implimenting this way, and it worked like a dream.
Controller Code:
SelectList typelist = new SelectList(context.CompanyType.ToList(), "CompanyTypeId", "Type", context.CompanyType);
ViewData["CompanyTypes"] = typelist;
View Code:
#Html.DropDownList("CompanyTypeId", (IEnumerable<SelectListItem>) ViewData["CompanyTypes"])
There may be bugs in this code - I haven't tested it - but what you basically want to do is:
var etId = ??? // EmployeeTypeId from your model
var employeeTypes = context.EmployeeTypes.Select(et => new SelectListItem
{
Value = et.EmployeeTypeId.ToString(),
Text = et.Type.ToString(),
Selected = et.EmployeeTypeId == etId
});
ViewData["EmployeeTypeList"] = employeeTypes.ToList();
Then in your view you can do
#Html.DropDownList("EmployeeType", ViewData["EmployeeTypeList"])

Resources