My View is bound to this model
public class HomepageViewModel
{
public HomepageViewModel()
{
Regions = new List<TMRegion>();
}
public List<TMRegion> Regions { get; set; }
public int SelectedRegion { get; set; }
public SelectList SelectListRegions
{
get
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var tmRegion in Regions)
{
items.Add(new SelectListItem()
{
Value = tmRegion.Value.ToString(),
Text = tmRegion.Display
});
}
return new SelectList(items);
}
}
}
My view is like this -
#model ProSell.Admin.Models.ViewModels.HomepageViewModel
#using (Html.BeginForm("Index", "Search", FormMethod.Post, new { viewModel = Model }))
{
#Html.HiddenFor(m=>m.Regions)
#Html.DropDownListFor(model => model.SelectedRegion, Model.SelectListRegions.Items as List<SelectListItem>, "Select a region")
<input type="submit"/>
}
My controller populates Regions like this -
// GET: Search
public async Task<ViewResult> Index(HomepageViewModel viewModel)
{
if (viewModel.Regions.Count == 0)
{
viewModel = new HomepageViewModel();
JavaScriptSerializer js = new JavaScriptSerializer();
viewModel.Regions =
js.Deserialize<TMRegion[]>(
await _ApiConsumer.ExecuteGetMethod("myurlinhere"))
.ToList();
}
return View(viewModel);
}
The Drop down is populated in the view. When i select a region and submit the HomepageViewModel has the SelectedRegion correctly set to whatever id was selected, but the collection of Regions is empty.
How do I maintain the list in the model on submit?
Generally you should attempt to reduce the amount of data the client sends back to the server especially with collections since it's far more efficient for the server to make a database call to retrieve the collection than have it passed back with the form data.
As Stephen said you can re-populate the collections Regions from your controller or if you need it when returning the view due to ModelState error you can add the population code into your model's constructor.
Also you can clean up your collection property like this:
public IEnumerable<SelectListItem> SelectListRegions
{
get
{
return Regions.Select(x => new SelectListItem
{
Text = x.Display,
Value = x.Value.ToString()
});
}
}
and in your View:
#Html.DropDownListFor(model => model.SelectedRegion, Model.SelectListRegions, "Select a region")
Related
I have the following two models, one of which contains a list of the other model i.e. UserModels.
public class UserModel
{
public int SelectedUserId { get; set; }
public SelectList UserOptions { get; set; }
public UserModel()
{
var users = new List<SelectListItem>
{
new SelectListItem { Text = "Mickey Mouse", Value = "1" },
new SelectListItem { Text = "Goofy", Value = "2" },
new SelectListItem { Text = "Donald Duck", Value = "3" },
};
UserOptions = new SelectList(users, "Value", "Text");
}
}
public class MyModel
{
public IList<UserModel> Users { get; set; }
public MyModel()
{
Users = new List<UserModel>();
}
}
When I attempt to bind this list of UserModels to a MVC Razor page with multiple DropDownList, the values do not bind and the selected item in the DropDownList is not displayed correctly.
#for(int i=0; i < Model.Users.Count; i++)
{
#Html.DropDownListFor(x => x.Users[i].SelectedUserId, Model.Users[i].UserOptions)
}
However, if I select different values in each DropDownList on the page and then post the form back to the server, the correct values bind within each individual UserModel in the List of models i.e. 'Users'.
Am I missing something here? Is this a known bug? Why is it when setting the values of SelectedUserId in each model on the server, does the correct option in the select list not bind, but selecting an option in the select list on the web page does work?
#Html.DropDownListFor works very weird way, when you init one, you have to init selected value too. So if you create list like this:
Users.Add(new UserModel { SelectedUserId = "2" });
you will have to assign selected item inside of UserModel :
List<SelectListItem> users=null;
public string SelectedUserId
{
get { return users.Where(u=>u.Selected).FirstOrDefault().Value; }
set {
var sUser=users.Where(u=>u.Value=value).FirstOrDefault();
sUser.Selected=true;
}
}
if you use net core much better to use " select " tag. It assigns automatically.
I'm trying to populate data from table in DropDownList using MVC4. Trying to figure it out how to get all the languages' titles into the DropDown in the Edit mode.
Models:
public class CategoryLanguage
{
public int ID { get; set; }
public int LanguageID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
public class Language
{
public int ID { get; set; }
public string Title { get; set; }
}
Controller:
public ActionResult Create()
{
using (MyDBContext db = new MyDBContext())
{
ViewBag.ID = new SelectList(db.Languages, "ID", "Title");
return View();
}
}
//
// POST: /Emp/Create
[HttpPost]
public ActionResult Create(CategoryLanguage newCatLang)
{
using (MyDBContext db = new MyDBContext())
{
if (ModelState.IsValid)
{
db.CategoryLanguages.Add(newCatLang);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ID = new SelectList(db.Languages, "ID", "Title", newCatLang.LanguageID);
return View(newCatLang);
}
}
View:
#model MultilanguageCategories.CORE.Models.CategoryLanguage
#{
ViewBag.Title = "Create";
}
<h2>Add New Item</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
#Html.DropDownList("ID", "--Select--")
}
Trying to figure it out how to get all the languages' titles into the DropDown when creating new CategoryLanguage entity. The error says: "The operation cannot be completed because the DbContext has been disposed." and this line marked: #Html.DropDownList("ID", "--Select--")
Change your get method "Create" as mentioned below :
public ActionResult Create()
{
var languages = new List<Language>();
using (MyDBContext db = new MyDBContext())
{
languages = db.Languages.ToList();
}
ViewBag.ID = new SelectList(languages, "ID", "Title");
return View();
}
Now you can use DropDownListFor as mentioned below :
#Html.DropDownListFor(model => model.[PropertyName], (IEnumerable<SelectListItem>)ViewBag.ID)
you're close...
You need to Add the languages select list to the viewbag (which you've already done, but with a badly named key)
ie: ViewBag.LanguagesList = new SelectList(db.Languages, "ID", "Title");
if you want an empty field that's easy enough too:
var langs = db.Languages.ToList().ConvertAll(x => new SelectListItem() { Value = x.ID, Text = x.Title });
langs.Insert(0, new SelectListItem() { Value = "", Text = "--Select--" });
ViewBag.LanguagesList = langs;
The DropdownList should be for a property in the model.
#Html.DropDownListFor(m => m.LanguageID, (IEnumerable<SelectListItem>)ViewBag.LanguagesList)
As it looks like you are using an Entity Framework class as your model you need to ensure the context is not disposed before the view is rendered.
As Per Microsoft's example link instantiate the context at the top of the controller, and drop the using statement in the Create method.
ie :
public class LanguageCategoryController : Controller
{
MyDBContext db = new MyDBContext();
public ActionResult Create()
{
ViewBag.LanguagesList = new SelectList(db.Languages, "ID", "Title");
// or replace the above line with the other example above
// if you want the empty "--select--" option
return View();
}
}
I would like to create a simple drop-down box that displays a list of countries. The data for it comes from the database and is accessed using the entity framework data context. The user should select a country before posting the data back.(simple validation check).
I've created the view model and have also written some code, but I'm not sure about my design and I also need help to complete the code. I've done some search, but I couldn't find a simple way of doing this. I'm still getting the data from context because I am still not sure about how to use repositories. At the moment, I just want the basic drop-down to work without getting too advanced. Please help. Thanks
Updated
View Model - Country.cs
public class Country
{ [Required]
public int Id { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
}
Controller
Public ActionResult CountriesDropDown()
{
Models.Country countryModel = new Models.Country();
using (ctx)
{
var model = (from q in ctx.Countries
select new SelectListItem
{
Text = q.CountryId,
Value = q.CountryName
}).ToList();
countryModel.Countries = model;
}
return View("Test",countryModel);
}
Countries View
#using (Html.BeginForm("DoSomething", "Test", FormMethod.Post))
{
#Html.DropDownListFor(model => model.Id, Model.Countries, "Please Select")
#Html.ValidationMessageFor(model => model.Id) //The validation part still Not Working. I want the user to select a country before submitting the form. Please help
<input type = submit value="submit" />
}
[HttpPost]
public ActionResult DoSomething(Models.Country Selectedcountry)
//country.Id holds the value of selected drop-down and it works fine
{
if (ModelState.IsValid)
//I need to do server-side validation and return back to client if Selectedcountry.Id is null (just in case, the client-side validation doesn't work)
{
return View();
}
else
{
return View("Test");
}
}
Thanks
Do this in your controller:
var model = new Country {
// assuming that the country with "id" exists
CountryId = ctx.Countries.Get(id).Id
};
model.Countries =
from q in ctx.Countries
select new SelectListItem {
Text = q.Id,
Value = q.Name
};
return view("countries", model);
Do this in your model
#model Models.Country
#Html.DropDownListFor(model => model.CountryId, model.Countries)
try this:
[Required(ErrorMessage = "Please select a Country")]
public string CountryCode{ get; set; }
public IEnumerable<SelectListItem> CountryList
{
get
{
return Country
.GetAllCountry()
.Select(Country=> new SelectListItem
{
Text = Country.Value,
Value = Country.Value
})
.ToList();
}
}
and then you could add a corresponding validation error message:
#Html.DropDownListFor(model => model.CountryCode, Model.CountryList, "select")
#Html.ValidationMessageFor(model => model.CountryCode)
I am working on a ASP.NET MVC3 code to bind the CheckBoxes using the data from the column of my SQL Database present in App_Data directory.
My table SysUser3 contains two columns with values as follows:
ProductName || ProductId
Pencil 1
Eraser 2
Pen 3
Model:
public class StoreModel
{
public List<ProductModel> Products { get; set; }
}
public class ProductModel
{
public string ProductName { get; set; }
public bool Selected { get; set; }
}
Controller:
[HttpGet]
public ActionResult CheckView()
{
var model = new StoreModel
{
Products = m.GetCheckBoxes()
};
return View(model);
}
//GetCheckBoxes method()
public IList<ProductModel> GetCheckBoxes()
{
IList<ProductModel> items = new List<ProductModel>();
using (SqlConnection con = new SqlConnection(#"Data Source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|DeveloperReport.mdf;User Instance=true"))
{
con.Open();
string cmdString = "SELECT ProductName FROM SysUser3";
using (SqlCommand cmd = new SqlCommand(cmdString, con))
{
using (SqlDataReader dataRead = cmd.ExecuteReader())
{
while (dataRead.Read())
{
items.Add(new ProductModel
{
Text = dataRead["ProductName"].ToString()
});
}
}
}
}
return items;
}
View:
#using (Html.BeginForm())
{
<div>
#Html.HiddenFor(x => x.ProductName)
#Html.CheckBoxFor(x => x.Selected)
#Html.LabelFor(x => x.Selected, Model.ProductName)
</div>
}
However, my code isn't working fine and I am not able to see the binding taking place.
I just get a empty checkbox when I run the code.
Can someone tell me what am I doing wrong
Thanks in advance
In your DAL you seem to be defining the item variable to be an List<ProductModel>() and inside the while clause you seem to be adding elements of type RoleModel to this list assigning only the Text property and not the Selected property which is what the checkbox is bound to. You seem to be selecting only the ProductName (SELECT ProductName FROM SysUser3).
There doesn't seem to be a Selected boolean column in your table, so you cannot populate properly this property and thus the generated checkbox in the view will never be checked.
I guess you will have to rethink your database design. But that's another topic.
As far as ASP.NET MVC is concerned, as long as you provide a valid view model to the view:
public ActionResult CheckView()
{
var model = new StoreModel
{
Products = new[]
{
new ProductModel { ProductName = "product 1", Selected = true },
new ProductModel { ProductName = "product 2", Selected = false },
new ProductModel { ProductName = "product 3", Selected = true },
}.ToList()
};
return View(model);
}
no matter where this data comes from, the corresponding checkboxes in the view will be properly bound:
#model StoreModel
#using (Html.BeginForm())
{
#Html.EditorFor(x => x.Products)
<button type="submit">OK</button>
}
and in the corresponding editor template (~/Views/Shared/EditorTemplates/ProductModel.cshtml) which will be rendered for each element of the Products collection of your view model:
#model ProductModel
<div>
#Html.HiddenFor(x => x.ProductName)
#Html.CheckBoxFor(x => x.Selected)
#Html.LabelFor(x => x.Selected, Model.ProductName)
</div>
And then obviously you will have the corresponding POST action which will take your view model as argument and call the underlying DAL to do some processing:
[HttpPost]
public ActionResult CheckView(StoreModel model)
{
// the model.Products collection will be properly bound here
// with the values that the user selected in the form
...
}
I am trying to build a Dropdownlist, but battling with the Html.DropDownList rendering.
I have a class:
public class AccountTransactionView
{
public IEnumerable<SelectListItem> Accounts { get; set; }
public int SelectedAccountId { get; set; }
}
That is basically my view model for now. The list of Accounts, and a property for returning the selected item.
In my controller, I get the data ready like this:
public ActionResult AccountTransaction(AccountTransactionView model)
{
List<AccountDto> accounts = Services.AccountServices.GetAccounts(false);
AccountTransactionView v = new AccountTransactionView
{
Accounts = (from a in accounts
select new SelectListItem
{
Text = a.Description,
Value = a.AccountId.ToString(),
Selected = false
}),
};
return View(model);
}
Now the problem:
I am then trying to build the Drop down in my view:
<%=Html.DropDownList("SelectedAccountId", Model.Accounts) %>
I am getting the following error:
The ViewData item that has the key 'SelectedAccountId' is of type 'System.Int32' but must be of type 'IEnumerable'.
Why would it want me to return the whole list of items? I just want the selected value. How should I be doing this?
You have a view model to which your view is strongly typed => use strongly typed helpers:
<%= Html.DropDownListFor(
x => x.SelectedAccountId,
new SelectList(Model.Accounts, "Value", "Text")
) %>
Also notice that I use a SelectList for the second argument.
And in your controller action you were returning the view model passed as argument and not the one you constructed inside the action which had the Accounts property correctly setup so this could be problematic. I've cleaned it a bit:
public ActionResult AccountTransaction()
{
var accounts = Services.AccountServices.GetAccounts(false);
var viewModel = new AccountTransactionView
{
Accounts = accounts.Select(a => new SelectListItem
{
Text = a.Description,
Value = a.AccountId.ToString()
})
};
return View(viewModel);
}
Step-1: Your Model class
public class RechargeMobileViewModel
{
public string CustomerFullName { get; set; }
public string TelecomSubscriber { get; set; }
public int TotalAmount { get; set; }
public string MobileNumber { get; set; }
public int Month { get; set; }
public List<SelectListItem> getAllDaysList { get; set; }
// Define the list which you have to show in Drop down List
public List<SelectListItem> getAllWeekDaysList()
{
List<SelectListItem> myList = new List<SelectListItem>();
var data = new[]{
new SelectListItem{ Value="1",Text="Monday"},
new SelectListItem{ Value="2",Text="Tuesday"},
new SelectListItem{ Value="3",Text="Wednesday"},
new SelectListItem{ Value="4",Text="Thrusday"},
new SelectListItem{ Value="5",Text="Friday"},
new SelectListItem{ Value="6",Text="Saturday"},
new SelectListItem{ Value="7",Text="Sunday"},
};
myList = data.ToList();
return myList;
}
}
Step-2: Call this method to fill Drop down in your controller Action
namespace MvcVariousApplication.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
RechargeMobileViewModel objModel = new RechargeMobileViewModel();
objModel.getAllDaysList = objModel.getAllWeekDaysList();
return View(objModel);
}
}
}
Step-3: Fill your Drop-Down List of View as follows
#model MvcVariousApplication.Models.RechargeMobileViewModel
#{
ViewBag.Title = "Contact";
}
#Html.LabelFor(model=> model.CustomerFullName)
#Html.TextBoxFor(model => model.CustomerFullName)
#Html.LabelFor(model => model.MobileNumber)
#Html.TextBoxFor(model => model.MobileNumber)
#Html.LabelFor(model => model.TelecomSubscriber)
#Html.TextBoxFor(model => model.TelecomSubscriber)
#Html.LabelFor(model => model.TotalAmount)
#Html.TextBoxFor(model => model.TotalAmount)
#Html.LabelFor(model => model.Month)
#Html.DropDownListFor(model => model.Month, new SelectList(Model.getAllDaysList, "Value", "Text"), "-Select Day-")