C# Is it possible to model bind multiple options? - c#

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

Related

Cannot display the list of names into the view

I have a list that I prepare in a ViewModel to take values from database table. The list assigned into a model class:
public class DType
{
public string DTName { get; set; }
}
And it get updated by the following method:
public static List<DType> GetDocTypesString(Entity DB, int RKey)
{
return DB.Database.SqlQuery<DType>(#"SELECT * FROM Names
WHERE NK = {0}", RKey).ToList();
}
And then I return the list (model) to the view to list the names into a select menu as the following:
The actual returned model to the view:
public List<DType> ihName { get; set; }
it gets populated by using the method above:
ihName = GetDocTypesString(DB, RKey);
And then, in the view, I use the below:
#Html.Partial("GettingNamesPartial", new ProjName.ViewModels.UploadingPartialViewModel
{
DropdownIHDocType = new SelectList(Model.ihEditorInstanceName)
})
The results are always like this:
Instead to displaying the actual names, the list (select) display:
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
The only thing that matches is the number of items is the same as the names on the database table.
Important Note:
Before trying to pull the names from the database, the list worked just fine by hard coding the names like the following:
DropdownIHDocType = new SelectList(new string[] { "Morgan", "Sam", "Shawn" })
ihName = GetDocTypesString(DB, RKey);
is your culprit. your getting a list of document types, not the variable name from each of those documents. basically your showing the class not its content. you need to get access to the actual document, then find the variable you need and assign that to ihName
so you're grabbing DType not DType.DTname which is what i assume your trying to list

How can I return an empty list instead of a null list from a ListBoxFor selection box in Asp.net MVC?

controller get action
IList<InputVoltage> inputVoltagesList = unitOfWorkPds.InputVoltageRepository.GetAll.ToList();
pdsEditViewModel.InputVoltageList = inputVoltagesList.Select(m => new SelectListItem { Text = m.Name, Value = m.Id.ToString() });
ViewModel
public IEnumerable<SelectListItem> InputVoltageList { get; set; }
public List<int> SelectedInputVoltages { get; set; }
View
#Html.ListBoxFor(m => m.SelectedInputVoltages, Model.InputVoltageList)
I want to receive a null list when a user makes no selections the selectedInputvoltages comes into my post controller action as null how do I get it to come in as an empty list?
I like both answers is there any benefit in using one over the other?
Either make sure it is initialized in the controller (or model/viewmodel) if null, or perhaps (ugly code though) use the coalesce operator to initialize on the fly if null:
#Html.ListBoxFor(m => m.SelectedInputVoltages, Model.InputVoltageList ?? new List<SelectListItem>())
If you initialize the list in the view model's constructor then it will always be at least an empty list. Anything which builds an instance of the view model would continue to set the list accordingly.
public class SomeViewModel
{
public List<int> SelectedInputVoltages { get; set; }
public SomeViewModel()
{
SelectedInputVoltages = new List<int>();
}
}
This way it will never be null in an instance of SomeViewModel, regardless of the view, controller, etc.
If you always want the view model's property to have a default value, then the best place to put that is in the view model. If that logic is instead placed in the controller or the view then it would need to be repeated any time you want to use it.

ASP.NET MVC dropdown-list from database

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.

MVC DropDownListfor() Basics

I have a Model which consist of Employees information. In my model there is a property called City which define the city of Employee in which he lives. The propery is shown below
public string City{get;set;}
Now I have a view which contains a form which will be filled by a employee to register. I want to use a dropdownlist for selecting cities. I think the below code will be used for dropdown as i discovered. My model name is Employee.
#Html.DropDownListFor(m=>m.City,new SelectList())
Please tell me that "is there any way to define the options for dropdownlist in SelectList() method directly Like ... in html?"
If not, where should i define the class for this drop down, where to call and where to render.I don't know where to define values? I am very confused because this is mvc and we have to seperate concern and i think we cannot define anything at anywhere?
Thanks in advance..
You have at least two options:
1.) Add a list, array, or any other collection type of cities to your model
2.) Add a SelectList property to your model
Option 1 can be something as simple as an array of strings, or can be, say, an IEnumerable of City objects. You would then need to transform this property to a collection of SelectListItem objects in the view as part of the DropDownList binding.
Option 2 has the advantage of being capable of direct binding to the DropDownList, but requires that you construct the list within the action method.
Then end result is the same, it's just a matter of how pedantic you want to be about SoC.
For example (assuming you add a property called Cities):
#Html.DropDownListFor(m=>m.City, Model.Cities.Select(city => new SelectListItem()
{
Text = city,
Value = city,
Selected = city == Model.City
})
EDIT:
To answer your comment, I have to make some assumptions. I will assume you have a model called EmployeeModel. This model has a property, City, that is a plain string. So, this is a partial of your model, as I assume it to be:
public class EmployeeModel
{
public string City { get; set; }
// ... other properties ...
}
So, if you need to add a property for binding to your dropdown, you would do one of the following:
public class EmployeeModel
{
public string City { get; set; }
public IEnumerable<string> Cities { get; set; }
// ... other properties ...
}
or
public class EmployeeModel
{
public string City { get; set; }
public SelectList Cities { get; set; }
// ... other properties ...
}
This new property will contain the list of cities that you allow your user(s) to pick from.
If you choose the first option, you load the IEnumerable from your datastore, and then use the first example above in your view, which uses LINQ to project each string in the Cities property into a new SelectListItem object.
If you go with the second option, you build a SelectList in the action prior to passing the model to the view. This isn't terribly difficult, as the class provides a constructor that takes an IEnumerable (your list of cities) and the "selected value," which will be the City property (see http://msdn.microsoft.com/en-us/library/dd460123%28v=vs.108%29.aspx). Your code would look something like:
model.Cities = new SelectList(GetCities(), model.City);
This, of course, assumes you have a helper method (GetCities()) to load your cities from wherever they are stored. Your view then would have something like this:
#Html.DropDownListFor(m=>m.City, model.Cities)
The view engine then uses these SelectListItems to build the <select> element and it's <option> elements.
You could have this in your model, it's quickly achieved, although I wouldn't recommend it:
public class Place
{
public string City{get;set;}
public SelectListItem[] Cities()
{
return new SelectListItem[2] { new SelectListItem() { Text = "London" }, new SelectListItem() { Text = "New York" } };
}
}
...and your view
#Html.DropDownListFor(m => m.City, Model.Cities())
I think the best place for something like this (but is a little more complicated) is your own htmlhelper and usage could look something like:
#html.CityDropDownFor(m => m.City)
You could cache the cities nicely and it keeps data and UI work out of your models.
If you want to learn more about creating your own helpers, I'd suggest a bit of a [read up].1

How do I transfer ViewModel data between POST requests in ASP.NET MVC?

I have a ViewModel like so:
public class ProductEditModel
{
public string Name { get; set; }
public int CategoryId { get; set; }
public SelectList Categories { get; set; }
public ProductEditModel()
{
var categories = Database.GetCategories(); // made-up method
Categories = new SelectList(categories, "Key", "Value");
}
}
Then I have two controller methods that uses this model:
public ActionResult Create()
{
var model = new ProductEditModel();
return View(model);
}
[HttpPost]
public ActionResult Create(ProductEditModel model)
{
if (ModelState.IsValid)
{
// convert the model to the actual entity
var product = Mapper.Map(model, new Product());
Database.Save(product);
return View("Success");
}
else
{
return View(model); // this is where it fails
}
}
The first time the user goes to the Create view, they are presented with a list of categories. However, if they fail validation, the View is sent back to them, except this time the Categories property is null. This is understandable because the ModelBinder does not persist Categories if it wasn't in the POST request. My question is, what's the best way of keeping Categories persisted? I can do something like this:
[HttpPost]
public ActionResult Create(ProductEditModel model)
{
if (ModelState.IsValid)
{
// convert the model to the actual entity
var product = Mapper.Map(model, new Product());
Database.Save(product);
return View("Success");
}
else
{
// manually populate Categories again if validation failed
model.Categories = new SelectList(categories, "Key", "Value");
return View(model); // this is where it fails
}
}
But this is an ugly solution. How else can I persist it? I can't use a hidden field because it's a collection.
I would use the repository to fetch whatever data is needed and don't think it's an ugly solution:
[HttpPost]
public ActionResult Create(ProductEditModel model)
{
if (!ModelState.IsValid)
{
// manually populate Categories again if validation failed
model.Categories = Repository.GetCategories();
return View(model);
}
// convert the model to the actual entity
var product = Mapper.Map(model, new Product());
Database.Save(product);
// I would recommend you to redirect here
return RedirectToAction("Success");
}
To further refactor this I would recommend you watching the excellent Putting Your Controllers on a Diet video presentation by Jimmy Bogard.
I typically implement my lists (for drop downs) as a readonly property. When the View gets the value the property is self contained on what it needs to return the values.
public SelectList Categories
{
get
{
var categories = Database.GetCategories(); // made-up method
return new SelectList(categories, "Key", "Value");
}
}
If necessary you can grab the currently selected item (i.e. validation failed) from the property containing the id that was posted and bound to the instance of your class.
In my case I have a BaseModel class where I keep all those property list as class attributes.
Like in the following sample:
public IEnumerable<SelectListItem> CountryList
{
get
{
return GetCountryList().Select(
t => new SelectListItem { Text = t.Name, Value = Convert.ToString(t.CountryID) });
}
}
GetCountryList() is a function that ask a Singleton for data. This would only happen once in the app lifecycle
Another way for doing this, and if those lists are pretty big, would be to have a static utility class with the lookup table that returns the SelectListItem.
If you need to access a list that change from time to time then simply dont use a Singleton class.

Categories

Resources