I have a model for person that has dictionary to hold Gender values (the values are added in a controller). I have created a viewmodel with person class and other properties. In controller I tried to add values to dictionary in person class through an instance of viewmodel. It does not throw an error but the dictionary value is always null. The code works if I do not use viewmodel and work with model directly. Important!!!! (I have to add values to dictionary via controller) Thanks for your help. Please code below.
In Model:
public class dictionary
{
[Display(Name ="Dictionary Dropdownlist")]
public Dictionary<string,string> dpdnDict { get; set; }
}
In ViewModel:
public class dictionaryviewmodel
{
public dictionary dictInViewModel {
get { return new dictionary(); }
set { }
}
}
In Controller:
public ActionResult Index(dictionaryviewmodel dictViewModel)
{
dictViewModel.dictInViewModel.dpdnDict.Add("M", "Male");
dictViewModel.dictInViewModel.dpdnDict.Add("F", "Female");
return View(dictViewModel);
}
First of all this code is indeed throwing an exception on this line
dictViewModel.dictInViewModel.dpdnDict.Add("M", "Male");
because dictViewModel.dictInViewModel returns new dictionary() and dictViewModel.dictInViewModel.dpdnDict is null because dpdnDict isn't set anywhere in code. If you want to make this code work change your classes
public class dictionaryviewmodel
{
public class dictionaryviewmodel
{
//this getter will create dictionary instance only once
//and will always return the same instance with previously added values
//also it instantiates dpdnDict object
public dictionary dictInViewModel { get; } = new dictionary()
{
dpdnDict = new Dictionary<string, string>()
};
}
}
And I don't think you pass any data into controller on request so I'd update controller as well
public ActionResult Index()
{
dictionaryviewmodel dictViewModel = new dictionaryviewmodel();
dictViewModel.dictInViewModel.dpdnDict.Add("M", "Male");
dictViewModel.dictInViewModel.dpdnDict.Add("F", "Female");
return View(dictViewModel);
}
I have a dropdown on which you can select multiple options.
The code for this dropdown is:
How can i bind multiple 'devices' in C# so that when this dropdown is loaded
model binding will automatically select all options which are passed into the view?
For your case you should use another helper - #Html.ListBoxFor it should generate select element with multiple attribute.
//note that i use MaintanceDevices property
#Html.ListBoxFor(x => x.MaintanceDevices, new SelectList(Model.Devises, "ID", "Description"), new { #class = "multiselect form-control"})
Also, don't set id attribute in helper. It's better to create another property in your ViewModel:
public List<int> MaintanceDevices { get; set; }
Populate it in Controller and MVC automatically generate right markup for your select element bind in on form POST.
In this situations, i would do the following inside the viewmodel
public string Devices { get; set; }
List<int> innerList;
public List<int> List
{
get
{
if (this.innerList == null)
{
if (string.IsNullOrEmpty(this.Devices))
{
this.innerList = this.Devices.Split(',').Select(x => int.Parse(x)).ToList();
}
else
{
this.innerList = new List<int>();
}
}
return this.innerList;
}
}
Where Devices is the binded property with the dropdown, which it returns all items separated by ,.
When you try to access List it will separate the items and return it as a List<int>.
And i'm parsing it to int because normally i see int's as ID's
But i'm looking forward for a better option.
PS
I do this when working with Select2
Devices property in your model should be a list of Ids (where is a simple type like int or a string) and not a list of Device models (Since you are using new SelectList(Model.Devices, "ID", "Description") in the Helper it is i see that Model.Devices is a collection of complex object)
So your model should look like:
public List<Device> AvailableDevices { get;set; }
public List<string> Devices { get;set; }
and the Helper should be
#Html.ListBoxFor(m=>m.Devices,new SelectList(Model.AvailableDevices , "ID", "Description"))
or
#Html.DropDownListFor(m=>m.Devices,new SelectList(Model.AvailableDevices , "ID", "Description", new {multiple="multiple"})
post action should receive either a List<string> as an argument or a full model:
[HttpPost]
public ActionResult Submit(List<string> devices)
or
[HttpPost]
public ActionResult Submit(YourModel model)
//where YourModel model is the same type that you are using to render your view
I have a controller that uses two classes. One is called IndexModel and the other IndexViewModel.
I pass the IndexViewModel into the IndexModel constructor.
[HttpGet]
public ActionResult Index()
{
var model = new IndexModel(new IndexViewModel());
var vm = model.GetViewModel();
return View("Index", vm);
}
Here is the view model class. Notice that the setter is private.
public class IndexViewModel
{
public IList<SelectListItem> SelectListItems { get; private set; }
public IndexViewModel()
{
this.SelectListItems = new List<SelectListItem>();
}
}
Here is the Model. When GetViewModel is called the SelectListItems list is populated and the view model returned.
public class IndexModel
{
private IndexViewModel vm;
public IndexModel(IndexViewModel IndexViewModel)
{
this.vm = IndexViewModel;
}
public IndexViewModel GetViewModel()
{
this.FillSelectListItems();
return vm;
}
private void FillSelectListItems()
{
// this data is pulled in from another class that queries a database...
var data = ...
foreach (var itm in data)
{
vm.SelectListItems.Add(new SelectListItem()
{
Value = itm.Id.ToString(),
Text = itm.Text,
});
}
}
}
I would appreciate any comments on how this is currently structured, but my main questions are:
Is it bad practice to write a bunch of methods, like FillSelectListItems(), that alter collection data and don't return a result?
Should I make the setter public so I can just return a list from my method and set the view model property that way?
What do you have to gain by making it private? A headache... make it public :)
There aren't any problems using view models in other view models... Imagine having a blog post... BlogPostViewModel... you would expect it to also have comments right? BlogPostViewModel > CommentViewModel
public class BlogPostViewModel
{
public string BlogPostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<CommentViewModel> Comments { get; set; }
}
Now when you render that, on your PostsController, at Posts/{id}, the view Posts/Index.cshtml would be rendered, and your comments can be rendered inside a partial view...
// Take this as pseudo code as there's some syntatic errors (can't be asked to open VS)
#for(int i = ... i < Model.Comments.Length... i++){
this.Html.Partial("_CommentsPartial.cshtml, Model.Comments[i])
}
On another note, if you wanted, you could pass your Model to the view as a JSON object as well without with this neat little hack... In your controller action...
this.ViewBag.Json = JsonConvert.SerializeObject<TViewModel>(viewModel);
And in your view just pick it backup...
<script> var json = #this.ViewBag.Json </script>
Hopefully this has provided some insight with regards to the purpose these View Models serve...
Ok, so I'm new to this whole MVC-world, but it seems to be a pretty good way of getting things done and I'm trying to make it work here.
The problem is:
I can't get data from my table in my SQL-database to a simple drop-down form on my registration page.
I have just no idea where to put the stuff, where to code to open the table, select the ids, where to put the response.write and how do I send it to the view?
My Model is this:
public class users
{
public string name {get; set;}
public int user_id {get; set;}
}
My Controller is this:
[HttpGet]
public ActionResult ListUser()
{
return View();
}
And my View is this:
#model Community.Models.users
I have googled for 2 days now and watched several videos on youtube but of no use, I can't find it. Please, anyone with some knowledge here? And please point me to some good tutorials and/or forums where I can browse for more questions I might have
Still no luck on this project..
I'm creating a form and within that form, i want a db-loop (IEnumerable).. But the current model is not a IEnumerable. I'm pretty much stuck, watched a bunch of tutorials and they all just list ONE connection, what if I want two models?
Here is my Controller, I get that you must pass a list to the view, right?
public ActionResult Registration()
{
return View(db.users.ToList());
}
How do i get hold of that list in my view witout an IEnumerable model?
#neoistheone, your example didnt help me much, my DB opens like this:
private DataBaseContext db = new DataBaseContext();
and i don't know how, but it opens the connection.
I've tried for so many hours now, its just silly, haven't slept for soo long!
I'm used to programming ASP-Classic fyi, and this is my first serious try to upgrade my knowledge about programing an up-to-date language and OOP.
Add the SelectList to your model:
public SelectList DropDownList { get; set; }
build the class for that collection:
public class MyListTable
{
public string Key { get; set; }
public string Display { get; set; }
}
and then in your controller, load the data for the MyListTable class from the database:
var list = new List<MyListTable>();
using (SqlConnection c = new SqlConnection(cString))
using (SqlCommand cmd = new SqlCommand("SELECT KeyField, DisplayField FROM Table", c))
{
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
list.Add(new MyListTable
{
Key = rdr.GetString(0),
Display = rdr.GetString(1)
});
}
}
}
var model = new users();
model.DropDownList = new SelectList(list, "Key", "Display");
and then finally, you need to send your model to the view:
return View(model);
Now in the Razor you can display this:
#Html.DropDownListFor(m => Model.DropDownList);
You of course can name these things better names, but you get the idea.
There a great answers already but Here is another approach.
You will use user as a model, ListUserViewModel as view-model and UserController as the contoller. The work of view-model is to carry all info needed to be displayed on the page from the controller without adding unwanted properties into the model class. In your case list of users from database into the drop down list.
Model:
public class User //By the way use singular when naming a class
{
public string name {get; set;}
public int user_id {get; set;}
}
View-model
public class ListUserViewModel
{
public list<User> Users{get; set;}
}
Controller
public class UserController : Controller
{
private DataBaseContext db = new DataBaseContext();
[HttpGet]
public ActionResult ListUser()
{
var users = db.Users.ToList();
var viewModel = new ListUserViewModel { Users = users };
return View(viewModel);
}
}
Now use ListUserViewModel instead of User in your view as a model
#model Community.Models.ListUserViewModel
and the drop down
#Html.DropDownListFor(m => m.Users, new SelectList(Model.Users, "user_id", "name"), " ")
Explanation:
You are creating drop down list for Users with Model.Users as select list data source. "user_id" as a value of the selected user and "name" as display label. the last argument( i put empty string " ") is a default value that the drop down will display before selection.
I hope this will help you or someone else.
Try this,
model
public string CoutryID { get; set; }
public List<SelectListItem> CountryList { get; set; }
Controller method which fill the list
public List<Country> getCountryList()
{
using (QRMG_VendorPortalDataContext _context = new QRMG_VendorPortalDataContext())
{
return (from c in _context.Countries
where c.IsDeleted == false
select c).ToList();
}
}
Drop down list in View
#Html.DropDownListFor(m => m.CoutryID,
new SelectList(Model.CountryList,
"CoutryID", "Value"))
I find this system works (and avoids using ViewBag):
View Model:
public class YourViewModel
{
// This could be string, int or Guid depending on what you need as the value
public int YourDropdownSelectedValue { get; set; }
public IEnumerable<SelectListItem> YourDropdownList { get; set; }
}
Controller:
// Get database values (by whatever selection method is appropriate)
var dbValues = db.YourEntity.ToList();
// Make Selectlist, which is IEnumerable<SelectListItem>
var yourDropdownList = new SelectList(dbValues.Select(item => new SelectListItem
{
Text = item.YourSelectedDbText,
Value = item.YourSelectedDbValue
}).ToList(), "Value", "Text");
// Assign the Selectlist to the View Model
var viewModel = new YourViewModel(){
// Optional: if you want a pre-selected value - remove this for no pre-selected value
YourDropdownSelectedValue = dbValues.FirstOrDefault(),
// The Dropdownlist values
YourDropdownList = yourDropdownList
};
// return View with View Model
return View(viewModel);
and in the View:
#Html.DropDownListFor(a => a.YourDropdownSelectedValue, Model.YourDropdownList, "select this text - change this to null to exclude", new { #class = "your-class" })
If you are really new to ASP.Net MVC, this is a quite good Tutorial that shows you how the MVC-Pattern works.
MVC3: http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/intro-to-aspnet-mvc-3
MVC4: http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4
Here is the sample-code to download: http://code.msdn.microsoft.com/Introduction-to-MVC-3-10d1b098
this is an helpful video: http://www.asp.net/mvc/videos/mvc-1/conference-presentations/creating-nerddinnercom-with-microsoft-aspnet-model-view-controller-mvc
this is my table in the database
take look it my Action controller
// GET: Letters
public ActionResult Index()
{
ViewBag.LetterStatus = new SelectList(LetterStatusService.GetAllLettersStatus(), "Id", (CultureHelper.GetCurrentCulture() == "ar") ? "NameArabic" : "Name", Request.QueryString["LetterStatus"]);
return View();
}
and in the view
#Html.DropDownList("LetterStatus")
the constructor I used is
new SelectList(
list<Objlect> myListFromDatabase,
string PropertyNameOfValueInHtml,
string PropertyNameOfDesplayInHtml,
string SelectedItemValue
);
this line Request.QueryString["LetterStatus"] because I send the Selected Items within QuerySrting
and based on CurrentCulture I chose what column to display
and the result are
but I think the best way to do this,,,, is to get or create the Items then Iterate throw them to generate the select tag manually. I described this approach well in this answer
hope this helps you
I had to put Everything together from about 5 different Stack Overflow entries. I'm a newbie that's not in love with EF. I prefer doing things in SQL. Mike Perrenoud got me started, but I had trouble getting his solution to compile properly in the view.
First, I declared my dropdown Id/Name inside my model and then declared a numeric selector plus a SelectList
public class BusinessType
{
public int Id { get; set; }
public string Name { get; set; }
}
public int SelectedBusinessId { get; set; }
public SelectList BusinessTypeddList { get; set; }
In my [HttpGet] (the one that does not pass in a model), I ALWAYS populate my dropdowns. I'm doing things in SQL Server because I find it easier than the EF abstraction and syntax (which baffles me). This code declares a List of business types and populates it directly from the database. Feel free to use a sproc or whatever. IMPORTANT: Don't forget to return the View(model) at the end or your View will get an object missing reference error.
var list = new List<MerchantDetail.BusinessType>();
using (var con = new SqlConnection(Common.DB_CONNECTION_STRING_BOARDING))
{
con.Open();
using (var command = new SqlCommand("SELECT Id, BusinessTypeDesc as Name FROM BusinessType order by Id", con))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
list.Add(new MerchantDetail.BusinessType
{
Id = reader.GetInt32(0),
Name = reader.GetString(1)
});
}
}
}
}
var model = new MerchantDetail();
model.BusinessTypeddList = new SelectList(list, "Id", "Name");
model.SelectedBusinessId = 0;
return View(model);
The view is simple. Mine looks like this.
#Html.DropDownListFor(m => m.SelectedBusinessId, Model.BusinessTypeddList, "Select One:", new { #class = "custom-select" });
NOTE: Setting the SelectedBusinessId to 0 only works if there's nothing in the model. It will be set to one of the dropdown values otherwise. That will happen in a different HttpGet that passes the model in.
I have the following model:
public class MyModel {
public int SelectedItemId { get; set; }
public SelectList PossibleItemsList { get; set; }
};
and in my controller I do the following:
var possibleItems = someSource.Select( item => new SelectListItem
{
Text = item.FirstMember,
Value = item.SecondMember
}).AsEnumerable();
var model = new MyModel();
model.SelectedItemId = somevalue;
model.PossibleItemsList = new SelectList(possibleItems, model.SelectedItemId);
return View( model );
and in my view I have this code:
#Html.DropDownList("SelectedItemId ", Model.PossibleItemsList )
and when the code runs the controller code seems to work okay but the view has a dropdown where all items just have "System.Web.Mvc.SelectListItem" text.
What am I doing wrong?
The constructor you are using treats its first argument as a list of objects that should be displayed in a list, and calls ToString on each of them to get both text and value for the corresponding list item. If these objects happen to be SelectListItem instances - it makes no difference, they are treated the same. SelectListItem.ToString is not defined and calls basic implementation, which is the string representation of the type. That is the why you are seeing list of "System.Web.Mvc.SelectListItem".
In your situation you do not need to construct enumerable of SelectListItem objects, just use another constructor of SelectList:
var model = new MyModel();
model.SelectedItemId = somevalue;
model.PossibleItemsList = new SelectList(
someSource, "FirstMember", "SecondMember", model.SelectedItemId);
return View(model);