I have a static dropdownlist and editor need to take the selected value from the dropdownlist and the written value from the editor and make a concatenation between the two values and save it in a Database table column in the post ActionResult:
This is the View:
#Html.DropDownList("Term.Description", new List<SelectListItem>
{
new SelectListItem{ Text="Winter", Value = "Winter-" },
new SelectListItem{ Text="Spring", Value = "Spring-" },
new SelectListItem{ Text="Fall", Value = "Fall-" },
new SelectListItem{ Text="Summer", Value = "Summer-" }
}, new { #class = "description-text" })
#Html.Editor("TermYear","", new { htmlAttributes = new { #class = "description-text", placeholder = "2018", data_placeholder = " " } })
ActionResult:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Term term, int[] applicantTypes)
{
ModelState.Remove("ApplicantTypes");
if (ModelState.IsValid)
{
if (applicantTypes != null && applicantTypes.Length > 0)
{
foreach (var item in applicantTypes)
{
term.ApplicantTypes.Add(db.ApplicantTypes.FirstOrDefault(x => x.ApplicantTypeID == item));
}
}
db.Terms.Add(term);
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ApplicantTypes = new MultiSelectList(db.ApplicantTypes, "ApplicantTypeID", "Name", term.ApplicantTypes.Select(x => x.ApplicantTypeID));
return View(term);
}
Finally, I need the `Term.Description = DropDownListSelectedValue-EditorValue'
I want to put a value from database because my dropdown already have a value the same as the text so I want a separate or different value from my text. Example code = 1, text = pathologist.
My controller:
public ActionResult MainHistopathologyForm(string id)
{
var patientprofileViewModel = new MDHPIStables();
patientprofileViewModel.histopathology = db.histopathology.Find(id);
patientprofileViewModel.roles = db.roles.Find(Session["role"]);
var PathologistList = new List<string>();
var PathologistQry = from d in db.pathologist
select d.pathologist;
PathologistList.AddRange(PathologistQry.Distinct());
TempData["pathologistlist"] = new SelectList(PathologistList);
return View(patientprofileViewModel);
}
MainHistopathologyForm.cshtml:
#Html.Partial("RolesHistopathologyForm", Model.roles, new ViewDataDictionary())
#Html.Partial("Partial_HistopathologyForm", Model.histopathology,
new ViewDataDictionary())
Partial_HistopathologyForm:
#{
ViewBag.concurring1 = TempData["pathologistlist"];
}
#Html.DropDownList("concurring1", "Select Pathologist")
#Html.DropDownList("Your ViewBag Name", null, "Select List", new { #class = "form-control", required = "required" })
I have four dropdownlistfor and a radiobuttonlistfor group. The radiobutton is for location type (which can either be an urban or rural location).
The first dropdownlistfor is the state which a user must select first before choosing either urban or rural. When the radiobuttonlistfor is selected it triggers a jquery click event which calls an action in my controller to populate the second dropdownlistfor for cities under the selected state and location type.
Controller
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetCitiesByStateId(int stateId)
{
if (stateId==0)
{
throw new ArgumentNullException("stateId");
}
var x = _repository.GetAllCitiesByStateId(stateId);
var result = (from s in x
select new
{
id = s.id,
name = s.CityName
}).ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetRuralArea(int stateId)
{
if (stateId == 0)
{
throw new ArgumentNullException("stateId");
}
var x = _repository.GetAllAreaInRural(stateId);
var result = (from s in x
select new
{
id = s.id,
name = s.AreaName
}).ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
View
State:
#Html.DropDownListFor(x => x.State.ID, Model._State(), "Select")
#Html.RadioButton("UrbanRural", "1", false, new { id = "urban" })
#Html.RadioButton("UrbanRural", "2", false, new { id = "rural" })
#Html.DropDownListFor(x => x.City.ID, Model._Cities)
#Html.DropDownListFor(x => x.AreaRural.ID, Model._AreaRural)
Button Click Code
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Registration model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Confirmation");
}
else
{
ViewBag.Selpwd = model.Password;
return View(model);
}
}
Issue:
I observed that when my button is clicked the city or area dropdownlistfor as the case may be empties. How do I retain the content after a postback?
I can't seem to pass any data via the ViewBag or ViewData to the View. It just keeps coming back with null.
ViewResult code:
public ViewResult EditProduct(Guid id)
{
var product = _repository.Products.FirstOrDefault(x => x.ID == id);
ViewData["Categories"] = _repository.Categories;
ViewData["CategoryList"] = _repository.Categories.Select(x => new SelectListItem { Text = x.Name, Value = x.ID.ToString(), Selected = product.ID == x.ID });
ViewBag.Test = "Hello";
return View(product);
}
and this is the razor code:
#model NightingalecrossMVC.Domain.Entities.Product
#{
var test = ViewData.Eval("CategoryList");
var test2 = ViewBag.Test;
ViewBag.Title = "Edit Treatment";
AjaxOptions ajaxOpts = new AjaxOptions
{
UpdateTargetId = "saveData",
HttpMethod = "Post",
LoadingElementId = "loader"
};
}
Why is this happening? It works fine on any other view?!
The reason for getting null values is because I had this:
public ViewResult CreateProduct()
{
return View("EditProduct", new Product());
}
It needed to be this:
public ViewResult CreateProduct()
{
ViewBag.CategoryList = _repository.Categories.Select(x => new SelectListItem { Text = x.Name, Value = x.ID.ToString() });
return View("EditProduct", new Product());
}
EDIT
Actually you can't make a selectlistitem list like that because of the ToString() method in the LINQ, it needs to be elongated with {} instead of new SelectListItem to make a proper function out of it. But then this will decrease readability. So the best solution is to make a function that returns IEnumerable then you can make a SelectList.
There has been some controversy about using SelectList and that DropDownList doesn't support that overload. However SelectList does implement IEnumerable so shouldn't therefore support SelectList.
I have a gender select field (--Select--, Male, Female) and I'm populating that in my controller. When the page loads, I want the gender that is selected in the model pm.Gender to be automatically selected when the page loads.
The values from pm.Gender come back as:
" "
"M"
"F"
View:
<%: Model.Gender %>
<%: Html.DropDownListFor(m => m.Gender, (IEnumerable<SelectListItem>)ViewData["gender"], new { #class = "span2" })%>
Controller:
gender = new[] { "Select", "Male", "Female" };
List<SelectListItem> genderselectList = new List<SelectListItem>();
foreach (string item in gender)
{
SelectListItem sli = new SelectListItem { Text = item, Value = item };
if (item.Trim().StartsWith(pm.Gender))
sli.Selected = true;
genderselectList.Add(sli);
}
ViewData["gender"] = genderselectList;
After debugging the application, I can see that genderselectList contains the proper data with Selected = true for the proper value that is supposed to be selected. But when the page loads, nothing is selected in the dropdown list that was supposed to be generated with the Html.DropDownListFor.
Edit: Does not work in any browser.
Anyone know what could be causing this problem? Any help would be appreciated.
Cheers.
EDIT: (After implementing Kaf's solution)
Ok so this is what I'm doing after implementing Kaf's solution.
View:
<%: Html.DropDownListFor(m => m.Gender, (SelectList)(ViewData["gender"]), new { #class = "span2" }) %>
Controller:
gender = new[] { "Select", "Male", "Female" };
List<SelectList> genderselectList = new List<SelectList>();
foreach (string item in gender)
{
SelectList sli;
if (item.Trim().StartsWith(pm.Gender))
sli = new SelectList(GetGender(), item, item, item);
else
sli = new SelectList(GetGender(), item, item);
//without selectedValue
genderselectList.Add(sli);
}
ViewData["gender"] = genderselectList;
When I do that, I get the following exception:
Unable to cast object of type 'System.Collections.Generic.List`1[System.Web.Mvc.SelectList]' to type 'System.Web.Mvc.SelectList'.
Anyone know what I'm doing wrong?
I suggest it's better if you use strongly typed property for SelectList (rather than using ViewBag/ViewData). I believe what you are expecting is that your dropdownlist to be pre-selected with the gender selection made in the model. Here is a solution (code is not 100% clean. But this will work)
Model
public class TestModel
{
public string Gender { get; set; }
public IEnumerable<SelectListItem> GenderList
{
get
{
List<SelectListItem> list = new List<SelectListItem> { new SelectListItem() { Text = "Select", Value = "Select" }, new SelectListItem() { Text = "Male", Value = "Male" }, new SelectListItem() { Text = "Female", Value = "Female" } };
return list.Select(l => new SelectListItem { Selected = (l.Value == Gender), Text = l.Text, Value = l.Value });
}
}
}
Controller Action
public ActionResult MyView()
{
TestModel m = new TestModel();
m.Gender = "Female";
return View(m);
}
MyView.cshtml
#model TestModel
#{
ViewBag.Title = "MyView";
}
<h2>MyView</h2>
#using (Html.BeginForm())
{
<div>
#Html.DropDownListFor(model => model.Gender, Model.GenderList)
</div>
}
OUTPUT
dropdown with 'Female' option selected
EDIT
Based on comments find below links to sample projects
1) https://github.com/prashanth-t/DropdownDemo_BareBones (Using the MVC 4 empty template. Smaller file size with bare minimum)
2) https://github.com/prashanth-t/DropdownDemo (Using the MVC 4 internet application template. Bigger file size)
This is a known bug in ASP.NET MVC Razor View. As per the known bug documentation
"The reason behind this problem is that asp.net MVC first looks for a match between the name of the drop down and property on the model. If there’s a match, the selected value of the SelectList is overridden. Changing the name of the drop down is all it takes to remedy the issue."
I'm here giving a small example which you can use to test the resolution.
var paymentTypeList = new List<SelectListItem>
{
new SelectListItem { Text = "Select Payment Type", Value = "NA" },
new SelectListItem { Text = "Card", Value = "Card" },
new SelectListItem { Text = "Paytm Wallet", Value = "Paytm Wallet" },
new SelectListItem { Text = "Cash", Value = "Cash", Selected = true },
new SelectListItem { Text = "Credit", Value = "Credit" },
new SelectListItem { Text = "Other", Value = "Other" }
};
ViewBag.paymentTypeList = paymentTypeList;
Resolution Option 1 (Easiest) - Change the Name of declaration id of select list id in MVC view e.g
#Html.DropDownList("paymentTypeListNew", (List<SelectListItem>)ViewBag.paymentTypeList, new { #class = "form-control select2 select1" })
Resolution 2: (Use only single constructor of #Html.DropDownList that matches viewbag/viewdata property)
To ensure that selected item (cash in this example) gets selected do the following in MVC Razor View. Use only the following constructor without any CSS or new object values
#Html.DropDownList("paymentTypeList")
Now if you are worried that you cannot initialize the CSS then you need to initialize the css programitally. For example if you are using Jquery then can you can use
$("#paymentTypeList").addClass("form-control");
$("#paymentTypeList").addClass("select2");
Method to get genders with select:
private Dictionary<string,string> GetGender(){
Dictionary<string, string> myDic = new Dictionary<string, string>();
myDic.Add(System.DBNull.Value.ToString(), "Select");
myDic.Add("Male", "Male");
myDic.Add("Female", "Female");
return myDic;
}
In the controller:
//without selectedValue
ViewData["gender"] = new SelectList(GetGender(), "Key", "Value");
OR
//"Male" as selectedValue
ViewData["gender"] = new SelectList(GetGender(), "Key", "Value", "Male");
In the view:
Html.DropDownListFor(m => m.Gender, (SelectList)(ViewData["gender"]),
new { #class = "span2" })
Try this instead in the controller:
string[] gender = new string[] {"Male", "Female"};
string selectedGender = gender.Where(x => x.StartsWith(pm.gender)).FirstOrDefault();
ViewData["gender"] = new SelectList(gender, selectedGender);
And in the view:
<%: Html.Dropdownlist(x => x.Gender, ViewData["gender"], "Select") %>
After searching myself for answer to this problem - I had some hints along the way but this is the resulting solution. It is an extension Method. I am using MVC 5 C# 4.52 is the target. The code below sets the Selection to the First Item in the List because that is what I needed, you might desire simply to pass a string and skip enumerating - but I also wanted to make sure I had something returned to my SelectList from the DB)
Extension Method:
public static class SelectListextensions
{
public static System.Web.Mvc.SelectList SetSelectedValue
(this System.Web.Mvc.SelectList list, string value)
{
if (value != null)
{
var selected = list.Where(x => x.Text == value).FirstOrDefault();
selected.Selected = true;
}
return list;
}
}
And for those who like the complete low down (like me) here is the usage.
The object Category has a field defined as Name - this is the field that will show up as Text in the drop down. You can see that test for the Text property in the code above.
Example Code:
SelectList categorylist = new SelectList(dbContext.Categories, "Id", "Name");
SetSelectedItemValue(categorylist);
select list function:
private SelectList SetSelectedItemValue(SelectList source)
{
Category category = new Category();
SelectListItem firstItem = new SelectListItem();
int selectListCount = -1;
if (source != null && source.Items != null)
{
System.Collections.IEnumerator cenum = source.Items.GetEnumerator();
while (cenum.MoveNext())
{
if (selectListCount == -1)
{
selectListCount = 0;
}
selectListCount += 1;
category = (Category)cenum.Current;
source.SetSelectedValue(category.Name);
break;
}
if (selectListCount > 0)
{
foreach (SelectListItem item in source.Items)
{
if (item.Value == cenum.Current.ToString())
{
item.Selected = true;
break;
}
}
}
}
return source;
}
You can make this a Generic All Inclusive function / Extension - but it is working as is for me.
Try this;
public static List<SelectListItem> ListSexo { get; } = new List<SelectListItem>
{
new SelectListItem{Selected =true, Value="N", Text="Seleccione"},
new SelectListItem{Value="F", Text="Femenino"},
new SelectListItem{Value="M", Text="Masculino"}
};
<select asp-for="Sexo" asp-items="Commons.ListSexo" class="form-control"></select>