Here is the Syntax of My Dropdown.
#Html.DropDownListFor(model => model.DealerIdRef, Model.Ddllist, " Select Dealer ", new { #class = "form-control"})
i want its default selected value and make it read-only so that user can not update selection. For this i'm using Jquery.
$('#DealerIdRef').val('#Session["MyID"]').trigger('change');
$("#DealerIdRef").attr('disabled', 'true');
this is setting the value and also exists in Console
At Controller it is still null
Edit
if i'm making some mistake then please help.
thanks in advance
Your javascript is setting the disabled attribute of the dropdownlist. Disabled form controls do not submit a value so the value of DealerIdRef in your model is its default (i.e. null because its int?).
If you want the value of the dropdownlist to be submitted, do not disabled it.
But based on i want its default selected value and make it read-only so that user can not update selection, then there is no point generating a dropdownlist, and in anycase, you set selected option by setting the value of the property your binding to. That is you set the value of DealerIdRef in the GET method before you pass the model to the view.
Since all you want is to display a value and have it posted back, then include a hidden input for the value and display the text
#Html.HiddenFor(m => m.DealerIdRef)
<div>...the txt you want to display...</div>
There is no point degrading performance by generating a SelectList and extra html when its not needed.
As a side note, your POST method would have throw this exception because you have not repopulated the SelectList in the POST method before you return the view.
I wrote a simple mock your question.
It can work. The simple code is on DropDownController
Here is the Source Code,I Upload to github.
ViewModel
public class DropDownViewModel
{
[Display(Name = "Dealer")]
public int? DealerIdRef { get; set; }
public IEnumerable<SelectListItem> Ddllist { get; set; }
}
Index View
Mock Your Submit action
#model Sample.Models.DropDownViewModel
#using (Html.BeginForm("ShowDDL", "DropDown", FormMethod.Post))
{
#Html.DropDownListFor(model => model.DealerIdRef, Model.Ddllist, " Select Dealer ", new { #class = "form-control" })
<button>Submit</button>
}
ShowDDL View
Show your select data.
#model Sample.Models.DropDownViewModel
<b>Your Select Value: </b> #Model.DealerIdRef
DropDownController
public ActionResult Index()
{
DropDownViewModel model = new DropDownViewModel()
{
Ddllist = GetDDL(),
DealerIdRef = 1
};
return View(model);
}
[HttpPost]
public ActionResult ShowDDL(DropDownViewModel viewModel)
{
return View(viewModel);
}
private IEnumerable<SelectListItem> GetDDL()
{
return new List<SelectListItem>()
{
new SelectListItem()
{
Text = "One",
Value = "1"
},
new SelectListItem()
{
Text = "Two",
Value = "2"
}
};
}
Using the following code i generate a select list in my controller and feed it into my view model.
var SelectListItems = om_repo.List().Select(x => {
var item = new SelectListItem();
item.Value = x.id.ToString();
item.Text = x.code;
return item;
});
createvm.allOccupations = new SelectList(SelectListItems);
Here is my view code
#Html.DropDownListFor(model => model.selectedOccupation, Model.allOccupations, "Choose one")
The output im getting is
<option>System.Web.Mvc.SelectListItem</option>
Why isnt it picking up the select list items Text and Values that are being fed. In my debugger i can see the values are set in the locals under text and value.
Because the DropDownlist doesn't want a SelectList; it wants an IEnumerable of SelectListItems.
Try just:
createvm.allOccupations = SelectListItems;
Model Class also needs to be:
public IEnumerable<SelectListItem> allOccupations { get; set; }
Not
public SelectList allOccupations { get; set; }
Scott Allen expanded on the problem here: https://odetocode.com/Blogs/scott/archive/2010/01/18/drop-down-lists-and-asp-net-mvc.aspx
I have a form, which includes three dynamic dropdownlists. They are all one-to-many relationships. The first dropdownlist has loaded values and the other two are empty at the start. When user selects one value from the 1st dropdownlist, the 2nd dropdownlist will load corresponding items; when user selects a value from the 2nd dropdownlist, the 3rd dropdownlist will load relating items.
User can create the form and submit. My CreateController GET and POST methods works well.
Now I need EditController to allow user to edit his form. The problem is how to display the 2nd and the 3rd dynamic dropdownlist with selected values?
In my viewModel:
public Nullable<int> Tech_ID { get; set; }
public string TechniqueName { get; set; }
public SelectList Techniques { get; set; }
public Nullable<int> BU_ID { get; set; }
public string BuName { get; set; }
public SelectList BusinessUnits { get; set; }
In my Edit Controller:
ViewBag.Bulist = new SelectList(AllBus, "BU_ID", "BU_Title", form.BU_ID);
var butechList = GetTechList(Convert.ToInt32(form.BU_ID));
IEnumerable<SelectListItem> butechs = butechList.Select(m => new SelectListItem()
{
Value = m.Tech_ID.ToString(),
Text = m.Technique.Tech_Title
});
ViewBag.Techlist = new SelectList(butechs, "Tech_ID", "Tech_Title", form.Tech_ID);
in View page:
#Html.DropDownListFor(model => model.BU_ID,
new SelectList((IEnumerable<SelectListItem>)#ViewBag.Bulist, "Value", "Text", Model.BU_ID),
new { id = "ddlBU" })
#Html.DropDownListFor(model => model.Tech_ID,
new SelectList((IEnumerable<SelectListItem>)#ViewBag.Techlist, "Value", "Text", Model.Tech_ID),
new { id = "ddlTechs" })
The first dropdownlist is working correctly, but the second is not.
Firstly, you have a view model containing SelectList properties, so make use of it rather than using ViewBag properties.
Next, delete the unnecessary last parameter (object selectedValue) in you SelectList constructors - your binding to a property in your model so it is ignored (internally the DropDwonListFor() method generated a new IEnumerable<SelectListItem> and sets the selectedValue based on the value of the property your binding to)
But the main issue is that your unnecessarily generating 3 IEnumerable<SelectListItem>. The first using
IEnumerable<SelectListItem> butechs = butechList.Select(...
which is correct. Then you try and create another one form it using
ViewBag.Techlist = new SelectList(butechs, "Tech_ID", "Tech_Title", form.Tech_ID);
but this time it will throw an exception because butechs is IEnumerable<SelectListItem> and SelectListItem does not contain properties Tech_ID and Tech_Title (it would need to be new SelectList(butechs, "Value", "Text") to prevent the error, but its pointless so just delete it). And then you try to create a 3rd IEnumerable<SelectListItem> inside the DropDownListFor() method (again its pointless extra ovehead).
Your code in the controller simply needs to be
var butechList = GetTechList(form.BU_ID.Value); // its already an int!
model.Techniques = new SelectList(butechList, "Tech_ID", "Tech_Title");
return View(model);
and in the view
#Html.DropDownListFor(m => m.Tech_ID, Model.Techniques) // not sure why you would need to change the id from the default id="Tech_ID" to id="ddlBU"?
I also suggest you study the code in this DotNetFiddle which shows an example of generating cascading dropdownlists. In particular the code in the private void ConfigureViewModel(ViewModel model) method, which will generate the correct SelectList's based on selected values, and can be called from both the Create() and Edit() methods (both the GET and the POST if you need to return the view)
I have tried this is RC1 and then upgraded to RC2 which did not resolve the issue.
// in my controller
ViewData["UserId"] = new SelectList(
users,
"UserId",
"DisplayName",
selectedUserId.Value); // this has a value
result: the SelectedValue property is set on the object
// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["UserId"])%>
result: all expected options are rendered to the client, but the selected attribute is not set. The item in SelectedValue exists within the list, but the first item in the list is always defaulted to selected.
How should I be doing this?
Update
Thanks to John Feminella's reply I found out what the issue is. "UserId" is a property in the Model my View is strongly typed to. When Html.DropDownList("UserId" is changed to any other name but "UserId", the selected value is rendered correctly.
This results in the value not being bound to the model though.
This is how I fixed this problem:
I had the following:
Controller:
ViewData["DealerTypes"] = Helper.SetSelectedValue(listOfValues, selectedValue) ;
View
<%=Html.DropDownList("DealerTypes", ViewData["DealerTypes"] as SelectList)%>
Changed by the following:
View
<%=Html.DropDownList("DealerTypesDD", ViewData["DealerTypes"] as SelectList)%>
It appears that the DropDown must not have the same name has the ViewData name :S weird but it worked.
Try this:
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
And then:
var list = new[] {
new Person { Id = 1, Name = "Name1" },
new Person { Id = 2, Name = "Name2" },
new Person { Id = 3, Name = "Name3" }
};
var selectList = new SelectList(list, "Id", "Name", 2);
ViewData["People"] = selectList;
Html.DropDownList("PeopleClass", (SelectList)ViewData["People"])
With MVC RC2, I get:
<select id="PeopleClass" name="PeopleClass">
<option value="1">Name1</option>
<option selected="selected" value="2">Name2</option>
<option value="3">Name3</option>
</select>
You can still name the DropDown as "UserId" and still have model binding working correctly for you.
The only requirement for this to work is that the ViewData key that contains the SelectList does not have the same name as the Model property that you want to bind. In your specific case this would be:
// in my controller
ViewData["Users"] = new SelectList(
users,
"UserId",
"DisplayName",
selectedUserId.Value); // this has a value
// in my view
<%=Html.DropDownList("UserId", (SelectList)ViewData["Users"])%>
This will produce a select element that is named UserId, which has the same name as the UserId property in your model and therefore the model binder will set it with the value selected in the html's select element generated by the Html.DropDownList helper.
I'm not sure why that particular Html.DropDownList constructor won't select the value specified in the SelectList when you put the select list in the ViewData with a key equal to the property name. I suspect it has something to do with how the DropDownList helper is used in other scenarios, where the convention is that you do have a SelectList in the ViewData with the same name as the property in your model. This will work correctly:
// in my controller
ViewData["UserId"] = new SelectList(
users,
"UserId",
"DisplayName",
selectedUserId.Value); // this has a value
// in my view
<%=Html.DropDownList("UserId")%>
The code in the previous MVC 3 post does not work but it is a good start. I will fix it. I have tested this code and it works in MVC 3 Razor C# This code uses the ViewModel pattern to populate a property that returns a List<SelectListItem>.
The Model class
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
The ViewModel class
using System.Web.Mvc;
public class ProductListviewModel
{
public List<SelectListItem> Products { get; set; }
}
The Controller Method
public ViewResult List()
{
var productList = new List<SelectListItem>();
foreach (Product p in Products)
{
productList.Add(new SelectListItem
{
Value = p.ProductId.ToString(),
Text = "Product: " + p.Name + " " + p.Price.ToString(),
// To set the selected item use the following code
// Note: you should not set every item to selected
Selected = true
});
}
ProductListViewModel productListVM = new ProductListViewModeld();
productListVM.Products = productList;
return View(productListVM);
}
The view
#model MvcApp.ViewModels.ProductListViewModel
#using (Html.BeginForm())
{
#Html.DropDownList("Products", Model.Products)
}
The HTML output will be something like
<select id="Products" name="Products">
<option value="3">Product: Widget 10.00</option>
<option value="4">Product: Gadget 5.95</option>
</select>
depending on how you format the output. I hope this helps. The code does work.
If we don't think this is a bug the team should fix, at lease MSDN should improve the document. The confusing really comes from the poor document of this. In MSDN, it explains the parameters name as,
Type: System.String
The name of the form field to return.
This just means the final html it generates will use that parameter as the name of the select input. But, it actually means more than that.
I guess the designer assumes that user will use a view model to display the dropdownlist, also will use post back to the same view model. But in a lot cases, we don't really follow that assumption.
Use the example above,
public class Person {
public int Id { get; set; }
public string Name { get; set; }
}
If we follow the assumption,we should define a view model for this dropdownlist related view
public class PersonsSelectViewModel{
public string SelectedPersonId,
public List<SelectListItem> Persons;
}
Because when post back, only the selected value will post back, so it assume it should post back to the model's property SelectedPersonId, which means Html.DropDownList's first parameter name should be 'SelectedPersonId'. So, the designer thinks that when display the model view in the view, the model's property SelectedPersonId should hold the default value of that dropdown list. Even thought your List<SelectListItem> Persons already set the Selected flag to indicate which one is selected/default, the tml.DropDownList will actually ignore that and rebuild it's own IEnumerable<SelectListItem> and set the default/selected item based on the name.
Here is the code from asp.net mvc
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
{
...
bool usedViewData = false;
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
selectList = htmlHelper.GetSelectData(name);
usedViewData = true;
}
object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string));
// If we haven't already used ViewData to get the entire list of items then we need to
// use the ViewData-supplied value before using the parameter-supplied value.
if (defaultValue == null && !String.IsNullOrEmpty(name))
{
if (!usedViewData)
{
defaultValue = htmlHelper.ViewData.Eval(name);
}
else if (metadata != null)
{
defaultValue = metadata.Model;
}
}
if (defaultValue != null)
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
...
return tagBuilder.ToMvcHtmlString(TagRenderMode.Normal);
}
So, the code actually went further, it not only try to look up the name in the model, but also in the viewdata, as soon as it finds one, it will rebuild the selectList and ignore your original Selected.
The problem is, in a lot of cases, we don't really use it that way. we just want to throw in a selectList with one/multiple item(s) Selected set true.
Of course the solution is simple, use a name that not in the model nor in the viewdata. When it can not find a match, it will use the original selectList and the original Selected will take affect.
But i still think mvc should improve it by add one more condition
if ((defaultValue != null) && (!selectList.Any(i=>i.Selected)))
{
selectList = GetSelectListWithDefaultValue(selectList, defaultValue, allowMultiple);
}
Because, if the original selectList has already had one Selected, why would you ignore that?
Just my thoughts.
This appears to be a bug in the SelectExtensions class as it will only check the ViewData rather than the model for the selected item. So the trick is to copy the selected item from the model into the ViewData collection under the name of the property.
This is taken from the answer I gave on the MVC forums, I also have a more complete answer in a blog post that uses Kazi's DropDownList attribute...
Given a model
public class ArticleType
{
public Guid Id { get; set; }
public string Description { get; set; }
}
public class Article
{
public Guid Id { get; set; }
public string Name { get; set; }
public ArticleType { get; set; }
}
and a basic view model of
public class ArticleModel
{
public Guid Id { get; set; }
public string Name { get; set; }
[UIHint("DropDownList")]
public Guid ArticleType { get; set; }
}
Then we write a DropDownList editor template as follows..
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<script runat="server">
IEnumerable<SelectListItem> GetSelectList()
{
var metaData = ViewData.ModelMetadata;
if (metaData == null)
{
return null;
}
var selected = Model is SelectListItem ? ((SelectListItem) Model).Value : Model.ToString();
ViewData[metaData.PropertyName] = selected;
var key = metaData.PropertyName + "List";
return (IEnumerable<SelectListItem>)ViewData[key];
}
</script>
<%= Html.DropDownList(null, GetSelectList()) %>
This will also work if you change ArticleType in the view model to a SelectListItem, though you do have to implement a type converter as per Kazi's blog and register it to force the binder to treat this as a simple type.
In your controller we then have...
public ArticleController
{
...
public ActionResult Edit(int id)
{
var entity = repository.FindOne<Article>(id);
var model = builder.Convert<ArticleModel>(entity);
var types = repository.FindAll<ArticleTypes>();
ViewData["ArticleTypeList"] = builder.Convert<SelectListItem>(types);
return VIew(model);
}
...
}
The problems is that dropboxes don't work the same as listboxes, at least the way ASP.NET MVC2 design expects: A dropbox allows only zero or one values, as listboxes can have a multiple value selection. So, being strict with HTML, that value shouldn't be in the option list as "selected" flag, but in the input itself.
See the following example:
<select id="combo" name="combo" value="id2">
<option value="id1">This is option 1</option>
<option value="id2" selected="selected">This is option 2</option>
<option value="id3">This is option 3</option>
</select>
<select id="listbox" name="listbox" multiple>
<option value="id1">This is option 1</option>
<option value="id2" selected="selected">This is option 2</option>
<option value="id3">This is option 3</option>
</select>
The combo has the option selected, but also has its value attribute set. So, if you want ASP.NET MVC2 to render a dropbox and also have a specific value selected (i.e., default values, etc.), you should give it a value in the rendering, like this:
// in my view
<%=Html.DropDownList("UserId", selectListItems /* (SelectList)ViewData["UserId"]*/, new { #Value = selectedUser.Id } /* Your selected value as an additional HTML attribute */)%>
In ASP.NET MVC 3 you can simply add your list to ViewData...
var options = new List<SelectListItem>();
options.Add(new SelectListItem { Value = "1", Text = "1" });
options.Add(new SelectListItem { Value = "2", Text = "2" });
options.Add(new SelectListItem { Value = "3", Text = "3", Selected = true });
ViewData["options"] = options;
...and then reference it by name in your razor view...
#Html.DropDownList("options")
You don't have to manually "use" the list in the DropDownList call. Doing it this way correctly set the selected value for me too.
Disclaimer:
Haven't tried this with the web forms view engine, but it should work too.
I haven't tested this in the v1 and v2, but it might work.
I managed to get the desired result, but with a slightly different approach. In the Dropdownlist i used the Model and then referenced it. Not sure if this was what you were looking for.
#Html.DropDownList("Example", new SelectList(Model.FeeStructures, "Id", "NameOfFeeStructure", Model.Matters.FeeStructures))
Model.Matters.FeeStructures in above is my id, which could be your value of the item that should be selected.
I want to add a dropdownlist in my form, with 2 values userid and username in my dropdownlist, and also I want to get the value selected by the user when I click the button. I'm new to MVC and so far, I have not worked on dropdownlist, tried few samples but nothing seems to be working the way I want.
I'll jump lots of MVC3 concepts. If you're really new to ASP.NET MVC, you should take a look at some tutorials.
This code should help you:
VIEW
#using (Html.BeginForm("ACTION NAME", "CONTROLLER NAME"))
{
<select name="select">
<option value="username" selected>User name</option>
<option value="userid">User id</option>
</select>
<input type="submit" />
}
ACTION
[HttpPost]
public ActionResult ACTIONNAME(string select)
{
//...
}
Please, note:
ACTION NAME and CONTROLLER NAME at the BeginForm helper. You will have to modify this at your code
The select name ("select") and the name of the argument at the action ("select"). This is not a coincidence, it's a convention. MVC uses the name attr to bind data
The selected attribute at the option will make it the default option
Regards
See one of the ways you can do it is send the list in a model property as the binding and for the value you can bind it to another property like :
public class YourModel
{
public List<UserList> OptionList { get; set; }
public String YourValue{get;set;}
}
public class UserList
{
public String UserName{get;set;}
public String UserId{get;set;}
}
#Html.DropDownListFor(model => model.YourValue, Model.OptionList, "")
In the helper there are overided options which are used to specify the value and text.
And Remember :
This is StackOverflow.
Even the Not working example which you have tried are important for the ones who try to help you since they are spending their precious bandwidths for u.
You don't need create a new model class for each view, just put this on controller:
ViewBag.FieldName = new SelectList(new List<SelectListItem>() {
new SelectListItem { Value = "userid", Text = "User ID" },
new SelectListItem { Value = "username", Text = "User name" }
});
And this on view:
#Html.DropDownList("FieldName")
You need to create a collection of SelectListItem like:
IEnumerable<SelectListItem> selectList =
from c in areaListResponse.Item
select new SelectListItem
{
Text = c.AreaName,
Value = c.Id.ToString()
};
Pass this selectList to your view:
return View(selectList);
In your cshtml:
#model IEnumerable<SelectListItem>
#Html.DropDownListFor(m => m.RequestAreaName, Model)
If you need complecated object, you may need a wrapper class like:
public class RaiseRequestModelWrapper
{
public IEnumerable<SelectListItem> GetModel { get; set; }
public RaiseRequestModel PostModel { get; set; }
}