I've created an MVC project using entity framework code first. My model is simply a form that gathers information.
public class Application
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleInitial { get; set; }
public string LastName { get; set; }
public int SSN { get; set; }
public DateTime DOB { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State {get; set; }
public string Zip { get; set; }
public int HomePhone { get; set; }
public int BusinessPhone { get; set; }
public int MobilePhone { get; set; }
}
My goal is to create a drop down list with all of the states, but I'm finding this to be very difficult given that I've already created the database via scaffolding with views and controllers. Is there a simple way to do this and tie it in with the existing database? I've searched for almost the entire day with no luck. An overview/explanation of what to include for the model/controller/view would be amazing!
Update: I've created a new model named "State" with properties "Id" and "StateName" and have created some states in the database. In my "Application" controller inside the Create action method I have:
Controller
public ActionResult Create()
{
ApplicationDbContext db = new ApplicationDbContext();
this.ViewData["Id"] = new SelectList(db.States.ToList(), "Id", "StateName");
return View();
}
View
#Html.DropDownList("Id")
Now the problem is I'm getting this error " There is no ViewData item of type 'IEnumerable' that has the key 'Id'." Would really appreciate help!
Its quite simple. Add an IEnumerable<SelectListItem> property to your model(Here I suggest you make a ViewModel that can have the exact same properties as Application with the below code included as a property). Then you just need to build the list and send it to your view
public IEnumerable<SelectListItem> States{ get; set; }
I will assume you want to retrieve the State values from the db. Here is how you will do it:
private IEnumerable<SelectListItem> GetAllStates()
{
IEnumerable<SelectListItem> list = from s in db.Applications
select new SelectListItem
{
Selected = false,
Text = s.State,
Value = s.State
};
return list;
}
Or this...
private IEnumerable<SelectListItem> GetAllStates()
{
IEnumerable<SelectListItem> list = db.Applications.Select(s => new SelectListItem
{
Selected = false,
Text = s.State,
Value = s.State
});
return list;
}
Then do something like this in your action:
var app = new Application
{
States = GetAllStates()
};
return View(app);
Then finally, use Razor on the view to display the Dropdown list like this
#Html.DropDownListFor(m => m.State, Model.States, "--Select a State--")
The 1st parameter is the property of the model to update, the 2nd is the list of data, and 3rd is the default message that will be displayed
Hope this helps.
Create a data layer that retrieves a list of what you want. Then use EF to get all the states.
//assuming you have a table of states..
var states = db.States();
The states table should be a Unique list of states.
var selectList = new List<SelectListItem>();
foreach(var thing in states){
//if you got everything, thus the ID field for the value...
selectList.Add(new SelectListItem {Text =thing.State, Selected = false, Value = thing.ID);
}
Make sure in your Viewmodel class that selectlist is a public property.....and set to what you did above. You also need to provied a string for the view selection post back.
StatesSelectList = selectList;
public IEnumberable<SelectListItem> StatesSelectList {get;set;}
public string SelectedState {get;set;}
In your view, do this:
#Html.DropDownListFor(p=>Model.SelectedState, Model.StatesSelectList)
Very simple Code step by step
1) In Entity Framework Class
var productsList = (from product in dbContext.Products
select new ProductDTO
{
ProductId = product.ProductId,
ProductName = product.ProductName,
}).ToList();
2) In Controller
ViewBag.productsList = new EntityFrameWorkClass().GetBusinessSubCategoriesListForDD();
3) In View
#Html.DropDownList("Product_ProductId", new SelectList(ViewBag.productsList, "ProductId", "ProductName"), new { #class = "form-control" })
OR
#Html.DropDownListFor(m=>m.Product_ProductId, new SelectList(ViewBag.productsList , "ProductId", "ProductName"), new { #class = "form-control" })
I assume there is a States model that has a Id and a StateName property.
Change to the list to ViewData["State"] to ensure easy binding on POST.
Id is the value that will be sent in the POST data ie.. State = Id. The StateName is what will be displayed in the Select list. So for your model this is not correct as State is a string. So needs to be
this.ViewData["State"] = new SelectList(db.States.ToList(), "StateName", "StateName");
Then in your view
#Html.DropDownList("State")
Related
I have a problem to get multi select dropdown list values.can anyone suggest me how to get select multiple dropdownlist values as well as how to get them in controller.
My code is like this:-
Model
public string BusinessUnitSiteSafetyRepresentative { get; set; }
Controller
[HttpPost]
public ActionResult AddClientBusinessUnitSite(LocalAddClientBusinessUnitSite local)
{
var query = from o in entitydb.systemusersorganizations.toList()
from c in entitydb.contacts.toList()
where o.orgId == clientId
select new SelectListItem
{
Text = c. Name;
Value = c.OrgId.toString()
}
ViewBag.list1 = query.ToList();
}
Well, I can get if single value is selected & can save to DB.But how to select multiple values as well as to get them in Controller so as to save them.
Note: - I am retrieving the dropdownlist values from DB as shown above.
View
#Html.ListBoxFor(x => Model.BusinessUnitSiteSafetyRepresentative,new
MultiSelectList((IEnumerable<SelectListItem>)#Viewbag.list1)
I have gone through some examples but none of them helped me.Please help me.
What I suggest is that your model needs to have a one to many relationship with the items in your multi select list.
An example is a Blog with multiple tags:
Your blog model may look like:
public class Blog
{
public Blog()
{
Tags = new List<Tag>();
}
public string BlogTitle{ get; set; }
public string Body{ get; set; }
public virtual ICollection<Tag> Tags{ get; set; }
}
And your tag model like so:
public int TagID{ get; set; }
public string TagName{ get; set; }
public virtual ICollection<Blog> Blogs{ get; set; }
Now I recommend you use a view model:
public class BlogViewModel
{
public Blog blog{ get; set; }
public List<int> SelectedTags { get; set; }
public virtual List<Tag> Tags{ get; set; }
public BlogViewModel()
{
}
public BlogViewModel(Blog _blog, List<Tag> _Tags)
{
blog = _blog;
Tags = _Tags;
SelectedTags = new List<int>();
}
}
And finally in your View (which inherits from the ViewModel);
#Html.ListBoxFor(m => m.SelectedTags,
new MultiSelectList(Model.Tags, "TagID", "Tag")
, null)
The JQuery Chosen plugin is excellent for this http://harvesthq.github.io/chosen/. You can use it by:
#Html.ListBoxFor(m => m.SelectedTags,
new MultiSelectList(Model.Tags, "TagID", "Tag")
, new { #class = "chzn-select", data_placeholder = "Tags..." })
Replace this with your own model and controllers and this should solve your problem. Also, this will work in your form for creating a new blog post, and for editing an existing post (adding and removing tags)
edit:
In your Blog Create controller action, you would populate this as:
public ActionResult Create()
{
var blog = new Blog();
var AllTags = from t in db.Tags
select t;
BlogViewModel viewModel = new BlogViewModel(blog,
Tags.ToList());
return View(viewModel);
}
public ActionResult Create(BlogViewModel blogViewModel)
{
Blog blog = blogViewModel.blog;
if (blogViewModel.SelectedTags != null)
{
foreach (var TagID in blogViewModel.SelectedTags)
{
Tag tag = db.Tags.Where(t => t.TagID == TagID).First();
blog.Tags.Add(tag);
}
}
db.Blog.Add(blog);
db.SaveChanges();
}
Try to change your modelproperty to a list type to accept multiple values:
public IEnumerable<string> BusinessUnitSiteSafetyRepresentative { get; set; }
Good answer by EvoNet. Its a different approach but worked well for me.
Here is Microsofts official way to do it: http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
Search for:
A join table is required in the database, however, as shown in the following database diagram:
I tried it and yes it created the table but I had to start editing the controller to get it to write to the table. Then I also had to think about creating cases for when a relationship already exists etc.
So I reveted to this method which worked just fine for me.
Using MVC 4, Entity Framework and Simple membership
* NEWB ALERT * Just getting started with scaffolding and CRUD.
In our scenario a user can only have one role (webpages_UsersInRoles table in DB)
I have a userProfile domain class but I am updating via viewModel.
My goal is to create a select list in the view which shows all the possible roles. When the view loads, the role that this user has, will be the first selected item in the list (selected selected attribute)
I've never even created a select list from a model or controller so please go easy me!
So far I have the following:
public class EditAdminModelVM
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public IEnumerable<string> UserInRole { get; set; }
//** I believe the function that returns the list of roles
a user is in is of type IEnumerable - though I could be wrong. **
[HiddenInput]
public int UserId { get; set; }
}
Then in my controller I have:
public ActionResult EditAdmin(int id = 0)
{
myDB db = new myDB();
var viewModel = new EditAdminModelVM();
var UserRoles = Roles.GetAllRoles();
SelectList UserRolesList = new SelectList(UserRoles);
viewModel = db.UserProfiles
.Where(x => x.UserId == id)
.Select(x => new EditAdminModelVM
{
FirstName = x.FirstName,
LastName = x.LastName,
Email = x.Email,
UserName = x.UserName,
UserId = x.UserId,
UserInRoles = Roles.GetRolesForUser(x.UserName)
}).FirstOrDefault();
ViewBag.UserRolesList = UserRolesList;
return View(viewModel);
}
The problem here is that I get a warning for this line:
Roles.GetRolesForUser(x.UserName) which says Cannot implicitly convert type string to Systems.Collections.Generic.List. I tried changing my Model property to type List<> but that results in the same error.
Any help would be appreciated!
You are converting a string[] to a list. This is not possible without some conversion.
try:
UserInRoles = new List(Roles.GetRolesForUser(x.UserName))
I have a service layer that exposes a method, which returns me a List, called GetStates.
public List<StateObject> GetStates()
My State Object is just a custom object I have created:
public class StateObject
{
public int stateId { get; set; }
public string description { get; set; }
public Boolean isDefault { get; set; }
}
In my models, I am trying to create a model that will be used for my display and modification screen of a task. One thing this will be used for is handling the display and selection of a Drop down box, which will give a list of States available for my Task. So, my model looks something like this (Removed properties we don't car about - it's a bit bigger than this:
public class TaskModifyModel
{
public int stateId { get; set; }
public string state { get; set; }
public SelectList states { get; private set; }
public TaskModifyModel()
{
states = new SelectList(
(new ReferenceService().GetStates()),
"stateId",
"description",
1);
}
}
So, stateId holds the selected state, state holds the text description of the selected state. In the constructor, I am attempting to create a states SelectList for the view... and populate it.
In the view, I then try to display the Drop Down List:
#Html.DropDownListFor(m=>m.stateId, new SelectList(Model.states, "stateId", "description", Model.priorityId))
This is failing, dismally.
DataBinding: 'System.Web.Mvc.SelectListItem' does not contain a property with the name 'stateId'.
I have searched, and I thought I was doing this the right way, but the error says I am not.. clearly. :) Could someone guide me on why it's not working, and also, is this the right way to do things?
Edit:
After assistance below, it's now working. If I am creating a new task (taskId==0), then I have to get the default value of the dropdown, as stored in my database.... So, is this clean? This is my working constructor for the object:
public TaskModifyModel()
{
var referenceService = new ReferenceService();
var p = referenceService.GetPriorities();
var s = referenceService.GetStates();
var defaultP = (from a in p where a.isDefault select a).FirstOrDefault();
var defaultS = (from a in s where a.isDefault select a).FirstOrDefault();
priorities = new SelectList(
(p),
"priorityId",
"description"
);
priorityId = taskId == 0 ? defaultP.priorityId : priorityId;
states = new SelectList(
s,
"stateId",
"description");
stateId = taskId == 0 ? defaultS.stateId : stateId;
}
Is it OK?
Your public SelectList states { get; private set; } is already a SelectList so you don't need to cast it again in your View.
Try this instead:
#Html.DropDownListFor(m=>m.stateId, Model.states)
And in your ViewModel, remove the parameter "SelectedValue". The #Html.DropDownListFor will initialize the dropdown to the right value.
public class TaskModifyModel
{
public int stateId { get; set; }
public string state { get; set; }
public SelectList states { get; private set; }
public TaskModifyModel()
{
states = new SelectList(
(new ReferenceService().GetStates()),
"stateId",
"description");
}
}
I'm new to MVC, so bear with me...
I've got my new form\view working (Creating and Adding a client)
But now I want to get the user so specifiy the Country where the new client is from A drop downlist. But im to sure how I to do this?
ViewModel
public class ClientNew
{
public string Company { get; set; }
public string Address { get; set; }
//New
public IEnumerable<CountryList> Country{ get; set; }
}
public class CountryList
{
public string Id { get; set; }
public string Name { get; set; }
}
Controller
(This is where is may be wrong, and is this the best way to do it?)
public ActionResult New()
{
var cl= new List<CountryList>();
cl.Add(new CountryList(){Id = "abcd",Name = "UK"});
cl.Add(new CountryList() { Id = "abce", Name = "USA" });
var model = new ViewModels.ClientNew();
model.Country= cl;
return View("New", model);
}
View (not sure how to plumb this in)
Html.DropDownList("Id" ??????)
In your view you will set up your dropdown on the property Id. This will be the current value selected in the dropdown when you POST to your form. The data that will be used for the dropdown is a SelectList called Countries that exists in your model.
#Html.DropDownListFor(m => m.Id, Model.Countries)
Your view model will have your Id, Name and Countries properties plus whatever else you need.
public class ClientNewViewModel {
public string Id { get; set; }
public string Name { get; set; }
public SelectList Countries { get; set; }
}
In your controller you need to pass the model to the view. You will need to populate the Countries SelectList. Keep in mind you will need to populate this value when you POST and fail validation as well.
public ActionResult New()
{
var model = new ClientNewViewModel();
model.Countries = new SelectList(service.GetCountries(),
"Id", "Name"); // set up what properties are used for id/name of dropdown
return View(model);
}
[HttpPost]
public ActionResult New(ClientNewViewModel model)
{
if( !ModelState.IsValid )
{
model.Countries = new SelectList(service.GetCountries(),
"Id", "Name");
return View(model);
}
// redirect on success
return RedirectToAction("Index");
}
Html.DropDownList("Id",
Country.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id
}));
There's a good blog post on the in's and out's of how to do this here -> http://277hz.co.uk/Blog/Show/10/drop-down-lists-in-mvc--asp-net
I am quite confused with how to effectively use the Html.DropDownList helper for ASP.NET MVC.
Background: I have a 5-page form, which saves data to the form each time "Next" is clicked. Users may navigate back and forth between sections, so previous sections will already be pre-populated with previously-entered data.
This works for TextBoxes. But not DropDownLists. I have tried a load of different methods, including:
How to add static list of items in MVC Html.DropDownList()
Setting selected item to DropdownList in MVC Application?
I have a ViewModel such taht I have got my lists and my Model (a LINQ-to-SQL generated class) as properties. eg:
public class ConsultantRegistrationFormViewModel
{
public IConsultantRegistration ConsultantRegistration { get; private set; }
public SelectList Titles { get; private set; }
public SelectList Countries { get; private set; }
public SelectList Currencies { get; private set; }
public int CurrentSection { get; private set; }
private ConsultantRegistrationFormViewModel(IConsultantRegistration consultantRegistration)
{
ConsultantRegistration = consultantRegistration;
CurrentSection = 1;
Titles = new SelectList(new string[] { "Mr", "Mrs", "Miss", "Ms", "Dr", "Sir" });
Countries = new SelectList(countries.Select(q => q.Name));
Currencies = new SelectList(currencies,"CurrencyCode","FriendlyForm");
}
}
My Controller's Edit Action on GET looks like:
public class ConsultantRegistrationController : Controller
{
public IConsultantRegistrationRepository ConsultantRegistrationRepository { get; private set; }
public ICountryRepository CountryRepository { get; private set; }
public IEnumerable<ICountry> Countries { get; private set; }
public ConsultantRegistrationController()
{
ConsultantRegistrationRepository = RepositoryFactory.CreateConsultantRegistrationRepository();
CountryRepository = RepositoryFactory.CreateCountryRepository();
Countries = CountryRepository.GetCountries().ToArray();
}
public ActionResult Edit(Guid id, int sectionIndex)
{
IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id);
SelectList bankBranchCountriesSelectList = new SelectList(Countries, "BankBranchCountry", "CountryName", consultantRegistration.BankBranchCountry);
ViewData["bankBranchCountrySelectList"] = bankBranchCountriesSelectList;
return View(new ConsultantRegistrationFormViewModel(consultantRegistration,sectionIndex, Countries,Currencies));
}
}
With my View doing:
<%: Html.DropDownList("ConsultantRegistration.BankBranchCountry",ViewData["bankBranchCountrySelectList"] as SelectList) %>
This gives me the error:
DataBinding:
'IWW.ArrowPay.ConsultantRegistration.Data.Country'
does not contain a property with the
name 'BankBranchCountry'.
Which it does, have a look at the schema of this property:
public interface IConsultantRegistration
{
Guid ID { get; set; }
[DisplayName("Branch Country")]
string BankBranchCountry { get; set; }
}
(My LINQ-to-SQL type ConsultantRegistration implemented IConsultantRegistration)
It seems that it is trying to bind to the wrong type, though?
If I use this in my view (and use my Controller's Countries property):
<%: Html.DropDownList("ConsultantRegistration.BankBranchCountry ",Model.Countries,"(select a Country)") %>
I get the saved value fine, but my model doesn't update on POST.
And if I use this in my view:
<%: Html.DropDownListFor(model=>model.ConsultantRegistration.BankBranchCountry ",Model.Countries,"(select a Country)") %>
I get the list, and it POSTs the selected value back, but does not pre-select the currently selected item in my model on the view.
So I have a bit of the solution all over the place, but not all in one place.
Hope you can help fill in my ignorance.
Ok, I solved it. Proper hacky, but it gets the job done.
I'm using the ViewData in my view:
<%: Html.DropDownList("bankBranchCountrySelectList", ViewData["bankBranchCountrySelectList"] as SelectList)%>
With the following in my controller:
public ActionResult Edit(Guid id, int sectionIndex)
{
IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id);
ViewData["bankBranchCountrySelectList"] = Countries.Select(q => new SelectListItem() { Text = q.Name, Value = q.Name, Selected = (q.Name.Trim().Equals(consultantRegistration.BankBranchCountry, StringComparison.InvariantCultureIgnoreCase)) }); // bankBranchCountriesSelectList;
return View(new ConsultantRegistrationFormViewModel(consultantRegistration,sectionIndex, Countries,Currencies));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, int sectionIndex, FormCollection formValues)
{
IConsultantRegistration consultantRegistration = ConsultantRegistrationRepository.GetConsultantRegistration(id);
UpdateModel(consultantRegistration);
ViewData["bankBranchCountrySelectList"] = Countries.Select(q => new SelectListItem() { Text = q.Name, Value = q.Name, Selected = (q.Name.Trim().Equals(consultantRegistration.BankBranchCountry, StringComparison.InvariantCultureIgnoreCase)) });
IEnumerable<RuleViolation> ruleViolations = consultantRegistration.GetRuleViolations(sectionIndex);
if (ruleViolations.Count() == 0)
{
// ...
}
else
{
ModelState.AddRuleViolations(ruleViolations);
return View(new ConsultantRegistrationFormViewModel(consultantRegistration, sectionIndex, Countries, Currencies));
}
}
Not ideal and breaks clean coding. No idea why it works, but that seems to be what MVC is all about with "convention over configuration".
This article was written with Multi-Select Lists in mind, but the principle applies equally to a single-selection drop down list:
http://www.stevefenton.co.uk/Content/Blog/Date/201002/Blog/How-To-Handle-Multiple-Select-Lists-In-ASP-NET-MVC/