DropDownListFor has unique value for all items - c#

I am using a razor helper DropDownListFor in order to have a dropdown list of Organizational Units from Active Directory (replicated in Database, it doesn't matter so much). The idea is you have a first list with all parent elements, and when clicking, I search my database to find the children elements, and so on until you reach a leaf (so to speak, last element). My problem is that when inspecting element in my browser I find that all value from the <option> markup are equal to the first id that I pass when clicking.
So here is my ViewModel:
public class SiteDirectionModel
{
public int id { get; set; }
public List<SelectListItem> Names { get; set; }
}
Then my first controller method (for parent elements) is the following :
public ActionResult CreateADUser()
{
List<SelectListItem> items = new List<SelectListItem>();
SiteDirectionModel sdM = new SiteDirectionModel();
//The below method gets all parent nodes from database
//_nonGenService is an instance of a service that can access my Repository
direction = _nonGenService.GetAllSiteDirection();
if (direction != null && direction.Count!=0)
{
items.Add(new SelectListItem
{
Text = dir.Name,
Value = dir.IDDirection.ToString()
});
}
sdM.Names = items;
return View(sdM);
}
else
return View("AccessError"); //A page in case of error
}
Then the second controller method to treat child elements:
public ActionResult GetSiteRF(SiteDirectionModel model)
{
SiteDirectionModel sdM = new SiteDirectionModel();
List<SelectListItem> items = new List<SelectListItem>();
//This method gets children elements from a specified id
//The table that looks has IDDirection as FK from first table
radioFrance = _nonGenService.GetSiteRFFromDirection(model.id);
direction = _nonGenService.GetAllSiteDirection();
int id;
string nameConcat = string.Empty;
//For loop to concatenate names
foreach(var dir in direction)
{
if (dir.IDDirection == model.id)
{
nameConcat = dir.Name + "-" + nameConcat;
break;
}
}
if (radioFrance.Count==1)
{//This condition would be to see if the name is equal to the current node so
//that we can exit the condition and access a form to create the user
Site_RadioFrance single = radioFrance.SingleOrDefault();
if (single.Name.Equals(nameConcat))
{
return View("CreateADForm", model);
}
}
else
{
foreach (var radio in radioFrance)
{
items.Add(new SelectListItem
{
Text = nameConcat+radio.Name,
Value = radio.IDDirection.ToString()
});
}
sdM.Names = items;
return View("CreateADUser",sdM);
}
return View("AccessError"); //Error treatement
}
My view loks like this :
#model MyProject.Models.SiteDirectionModel
<h2>Create an account in Active Directory</h2>
#using (Html.BeginForm("GetSiteRF", "Create", FormMethod.Post))
{
#Html.DropDownListFor(x => x.id, Model.Names);
<input type="submit" value="Selectionner" class="btn btn-primary"/>
}
Now say you have the item clicked with IDDirection=10 then all my child elements have
<option value=10>parent1-child1</option>
<option value=10>parent1-child2</option>
<option value=10>parent1-child3</option>
<option value=10>parent1-child4</option>
I don't know how to fix this, any ideas? because then my model id has this value, and I somehow thought that it would apply a value for each different option, I don't understand why it doesn't?
Thanks!

Related

.NET 6 - Set SelectListItem to Selected?

I have a DropDownList which I populate like below:
Controller
IEnumerable<Category> categories = _db.Category.ToList();
var selectList = _db.Category.Select(i => new SelectListItem()
{
Text = i.Name,
Value = i.Id.ToString()
});
ViewBag.categoriesSelectList = selectList;
And use in view like so:
<select asp-for="Category" name="categoryID" asp-items="#ViewBag.categoriesSelectList" class="form-control">
<option>Vælg Kategori:</option>
</select>
However, I can't seem to figure out how I can set the already selected value, so the dropdown "starts" on that value. I tried enumerating over the selectList and changing the Selected attribute of the SelectListItem, but it doesn't work since it won't save the changes I make.
Hope my question makes sense :) thanks all.
Option 1:
Modify your code to include Selected property when creating list of SelectListItem items:
var selectList = _db.Category.Select(i => new SelectListItem()
{
Text = i.Name,
Value = i.Id.ToString(),
Selected = /* Some condition that is true when the current item should be selected */
});
Option 2:
Define a view model with structure that might be referenced in the <select> tag:
public class SelectViewModel
{
public string Category { get; set; }
public List<SelectListItem> Categories { get; set; }
}
The action method:
public IActionResult Categories()
{
var model = new SelectViewModel() ;
model.Categories = _db.Category.Select(i => new SelectListItem()
{
Text = i.Name,
Value = i.Id.ToString()
});
model.Category = ... your_code_to_set_default_selection;
return View(model);
}
The view:
#model SelectViewModel
<select asp-for="Category" asp-items="#Model.Categories"></select>
Can find some mode information in the documentation: The Select Tag Helper

c# - render list of checkboxes, always returned as checked

Dears,
Please could you help with below problem:
I want to render list of checkbox in my view.
#model IEnumerable<CFts.Models.CFModel>
...
#foreach (var test in ViewBag.CF_list)
{
if (test.Text != "" && test.Text != " ")
{
<div class="checkbox">
<label><input value="#test.Value" id="CF_list_" name="CF_list_" #(test.Selected == true ? "checked" : "") type="checkbox"> #test.Text</label>
</div>
}
}
OK, checkbox on the page.
CF_list generated in controller (SelectListItem)
But problem that - if send this form, at least one of checkboxes all time marked as selected. For example: 1. I selected two chekckboxed, send form - everything is OK. 2. I remove all ticks and send form - one of the checkbox (last clicked) indicated as selected.
Why?
CF_List is SelectListItem
Another question:
Please could you help me to understand very simple thing
I have model with my class:
public class VendorAssistanceViewModel
{
public string Name { get; set; }
public bool Checked { get; set; }
}
public partial class CSModel : IEntity
{
public CSModel()
{
VendorAssistances = new[]
{
new VendorAssistanceViewModel { Name = "DJ/BAND" },
new VendorAssistanceViewModel { Name = "Officiant" },
new VendorAssistanceViewModel { Name = "Florist" },
new VendorAssistanceViewModel { Name = "Photographer" },
new VendorAssistanceViewModel { Name = "Videographer" },
new VendorAssistanceViewModel { Name = "Transportation" },
}.ToList();
}
public IList VendorAssistances { get; set; }
I have view:
#model IEnumerable<CSTS.Models.CSModel>
... some html code...
and how here to show array of checkboxes from Model, using VendorAssistances ?
I know that this is very simple, I read a lot of docs, but still can not understand
Thank you!
Do not set the checked attribute, let the value attribute determine whether it is checked or not.
Change
<label><input value="#test.Value" id="CF_list_" name="CF_list_" #(test.Selected == true ? "checked" : "") type="checkbox">#test.Text</label>
To
<label><input value="#test.Value" id="c_" name="CF_list_" type="checkbox">#test.Text</label>
UPDATE: Just to make this easier to understand..
Do not use a SelectListItem for CF_List, use this instead. SelectListItem is used for drop down lists.
public class CFListCheckbox
{
public bool IsChecked { get; set; } // Add a property to know if the checkbox should be checked or not
public string Text { get; set; }
public object Value { get; set; } // Change as needed
}
In your GET action..
// Assign an ICollection<CFListCheckbox> to your ViewBag.CF_list
ICollection<CFListCheckbox> cfListCB = cfCollection.Select(r => new CFListCheckbox()
{
IsChecked = false,
Text = r.SomeProp,
Value = r.SomePropOrWhatever
}).ToList();
ViewBag.CF_list = cfListCB;
On your view, use the Html.Checkbox to create your checkboxes.
#foreach (var test in ViewBag.CF_list)
{
if (!string.IsNullOrWhiteSpace(test.Text))
{
<div class="checkbox">
<label>
#Html.Checkbox("CF_list_", test.IsChecked, new { Value = test.Value }) #test.Text
</label>
</div>
}
}
On your POST action, just set the ViewBag.ViewBag.CF_list in case your post fails and goes back to the view.
// Assign an ICollection<CFListCheckbox> to your ViewBag.CF_list
ICollection<CFListCheckbox> cfListCB = cfCollection.Select(r => new CFListCheckbox()
{
IsChecked = false,
Text = r.SomeProp,
Value = r.SomePropOrWhatever
}).ToList();
// Add logic to re-assign the IsChecked property for your ViewBag.CF_list
foreach(var entry in model.CF_list_)
{
CFListCheckbox item = cfListCB.FirstOrDefault(r => r.Text == entry.SomeProp && r.Value == entry.SomePropOrWhatever);
if(item != null)
{
item.IsChecked = true;
}
}
ViewBag.CF_list = cfListCB;
return View(model);
Please note that the sample code is just to give you an idea on what you can do. It is not absolute. Optimize it as needed.

How Do I carry dropdown value selected in Asp.net MVC

Hi I have Dropdown in Index page where user needs to select lists. Values are coming from Database. I took this dropdown value into session so I can carry this to Httppost.
Below is my code in Index page :
var activitydropdown = orderdata.uspApp_ActivityPageReportname(Convert.ToInt32(newid)).ToList();
List<SelectListItem> activitypage = new List<SelectListItem>();
if (activitydropdown != null && activitydropdown.Count > 0)
{
foreach (var activityresults in activitydropdown)
{
activitypage.Add(new SelectListItem
{
Text = activityresults.name,
Value = activityresults.id.ToString(),
});
}
}
ViewData["activitydropdown"] = activitypage;
Session["activitydropdown"] = activitypage;
And this is my code in view :
#using (Html.BeginForm("Index", "Automation", new { step = "2" }, FormMethod.Post, new { id = "frmIndex" }))
{
#Html.DropDownList("DrpaActivity", ViewData["activitydropdown"] as List<SelectListItem>, "All", new { style = "margin-left:694px;margin-bottom:20px;", onchange = "submit();" })
Now when user selects list from dropdown, i need to carry that text to my httpost index. Now in httpost index, in debug mode if i see this code :
var sessionlistautomation = Session["activitydropdown"];
I can see text and value and selected is false for every item. So how can i carry text here selected from Index to httpost, so when user selects list from dropdown, it stores that text value.
It will be available in your Request i.e.
Request["DrpaActivity"]
However I would strongly advise using ViewModels instead as they're typesafe, less room for error and easier to use.
If you create a view model, like below:
public class AViewModel
{
public string DrpaActivity { get; set; }
public List<SelectListItem> ActivitySelectList { get; set; }
}
In your Index you can return it like this:
public ActionResult Index()
{
var model = new AViewModel();
// set the select list i.e.
model.ActivitySelectList = // get from db etc
return View(model);
}
Then in your view declare the model at the top
#model AViewModel
...
Set your dropdown like this:
#Html.DropDownListFor(m => m.DrpaActivity, Model.ActivitySelectList as List<SelectListItem>, "All", new { style = "margin-left:694px;margin-bottom:20px;", onchange = "submit();" })
You can then get your selected drop-down in your post as follows:
[HttpPost]
public ActionResult Index(AViewModel model)
{
var isValid = model.DrpaActivity;
return View(model);
}

Set selected value in dropdown list

How do I set the selected value on a drop down list? Here is what I have so far:
#model Web.Models.PostGraduateModels.PlannedSpecialty
#Html.DropDownList("PlannedSpecialtyID")
//controller
[HttpGet]
public PartialViewResult PlannedSpecialty()
{
// Get Planned Specialty ID
var pgtservice = new PgtService();
PostGraduateModels.PlannedSpecialty plannedSpecialty = pgtservice.GetPlannedSpecialtyId();
// Get Data for Planned Specialty DropDown List from SpecialtyLookup
var pgtServ = new PgtService();
var items = pgtServ.GetPlannedSpecialtyDropDownItems();
ViewBag.PlannedSpecialtyId = items;
return PartialView(plannedSpecialty);
}
// service
public IEnumerable<SelectListItem> GetPlannedSpecialtyDropDownItems ()
{
using (var db = Step3Provider.CreateInstance())
{
var specialtyList = db.GetPlannedSpecialtyDdlItems();
return specialtyList;
}
}
// data access
public IEnumerable<SelectListItem> GetPlannedSpecialtyDdlItems()
{
IEnumerable<Specialty> specialties = this._context.Specialties().GetAll();
var selList = new List<SelectListItem>();
foreach (var item in specialties)
{
var tempps = new SelectListItem()
{
Text = item.Description,
Value = item.Id.ToString()
};
selList.Add(tempps);
}
return selList;
}
I would recommend you to avoid using ViewBag/ViewData/ Weekly typed code. Use strongly typed code and it makes it more readable. Do not use the Magic strings/ Magic variables. I would add a collection property to your ViewModel to hold the SelectList items and another property to hold the selected item value.
public class PlannedSpecialty
{
public IEnumerable<SelectListItem> SpecialtyItems { set;get;}
public int SelectedSpeciality { set;get;}
//Other Properties
}
and in your Get action, If you want to set some Item as selected,
public PartialViewResult PlannedSpecialty()
{
var pgtServ = new PgtService();
var vm=new PlannedSpecialty();
vm.SpecialtyItems = pgtServ.GetPlannedSpecialtyDropDownItems();
//just hard coding for demo. you may get the value from some source.
vm.SelectedSpeciality=25;// here you are setting the selected value.
return View(vm);
}
Now in the View, use the Html.DropDownListFor helper method
#Html.DropDownListFor(x=>x.SelectedSpeciality,Model.SpecialtyItems,"select one ")
Use the selected property of the SelectListItem class:
selList.Selected = true;

Second dropdown list selected item does not change in ASP.NET MVC

I'm a bit confused by the behavior of ASP.NET MVC with it not changing the value of a dropdown list after a POST. Can someone explain how to do this.
First of all I have a model that looks like this:
public class Test
{
public int OneID { get; set; }
public IEnumerable<SelectListItem> OneList
{
get
{
yield return new SelectListItem
{
Text = "Red",
Value = "0"
};
yield return new SelectListItem
{
Text = "Green",
Value = "1"
};
yield return new SelectListItem
{
Text = "Blue",
Value = "2"
};
}
}
public int TwoID { get; set; }
public IEnumerable<SelectListItem> TwoList
{
get
{
yield return new SelectListItem
{
Text = "Ruby",
Value = "0"
};
yield return new SelectListItem
{
Text = "Gem",
Value = "1"
};
yield return new SelectListItem
{
Text = "Bronze",
Value = "2"
};
}
}
}
The view has this snippet of code in the body content:
<% using (Html.BeginForm("Index", "Home", FormMethod.Post))
{ %>
<table>
<tr>
<td>
<% =Html.DropDownList("OneID", Model.OneList, new
{ #onchange = "this.form.submit();" })%>
</td>
<td>
<% =Html.DropDownList("TwoID", Model.TwoList)%>
</td>
</tr>
</table>
<% } %>
And the GET and POST actions look like this:
public ActionResult Index()
{
Test test = new Test();
test.OneID = 0;
test.TwoID = 0;
return View(test);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Test test)
{
test.TwoID = test.OneID;
return View(test);
}
What I'm trying to achieve is to change the selected item in the second drop down to match the first drop down each time the first drop down is changed. So I'm getting the selected value from the first drop down and assigning it to the ID used for the second drop down and then returning the same model. The first drop down is correctly set in the view but not the second one.
Ideas?
The reason this doesn't work the way you expect it is because when the DropDownList helper tries to render the select element it first looks for posted values that match the name which in this case is TwoID and use this value instead of the value in the model. This is the same with a TextBox for example. If you use this helper and in the POST controller action you modify the value of the model it will still show the old value. That's just how helpers work. They bind from POSTed values.
There are two possible workarounds:
Use javascript to synchronize both dropdowns:
#onchange = "document.getElementById('TwoID').value = this.value; this.form.submit();"
BTW this should be done in an unobtrusive way in a separate javascript file:
$(function() {
$('#OneID').change(function() {
$('#TwoID').val($(this).val());
this.form.submit();
});
});
Write your own helper or generate the select manually (less recommended)

Categories