I've encountered some problems using DropDownList in ASP.NET MVC lately.
I want to save value of selected item to member called Wydzialy.
Sorry for not translating some names, they doesn't matter I think :)
Here is what I have:
View:
<div class="form-group">
#Html.LabelFor(model => model.Wydzial, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.Wydzial, (List<SelectListItem>)ViewBag.Wydzialy)
</div>
</div>
Model:
public class Student
{
public int Id { get; set; }
public int NumerIndeksu { get; set; }
public string Imie { get; set; }
public string Nazwisko { get; set; }
public int Semestr { get; set; }
public virtual Wydzial Wydzial { get; set; }
}
Controller:
public ActionResult Create()
{
var wydzialy = db.Wydzialy.ToList();
var lista = wydzialy.Select(W => new SelectListItem()
{
Text = W.Nazwa
}).ToList();
ViewBag.Wydzialy = lista;
return View();
}
Your trying to bind the dropdown to a complex object. A <Select> only posts backs a value type (in your case the text of the selected option).
Either bind to a property of Wydzial
#Html.DropDownListFor(x => x.Wydzial.Nazwa, (List<SelectListItem>)ViewBag.Wydzialy)
or preferably use a view model that includes a property to bind to and the SelectList
public class StudentVM
{
public int Id { get; set; }
// Other properties used by the view
public string Wydzial { get; set; }
public SelectList Wydzialy { get; set; }
}
Controller
public ActionResult Create()
{
StudentVM model = new StudentVM();
model.Wydzialy = new SelectList(db.Wydzialy, "Nazwa", "Nazwa")
return View(model );
}
View
#model StudentVM
....
#Html.DropDownListFor(x => x.Wydzial, Model.Wydzialy)
Note you appear to be binding only to the Nazwa property of Wydzial. Typically ou would display a text property but bind to an ID property.
Related
my development environment is ASP.NET MVC 5 using Entity Framework 6 using a code-first workflow.
My problem: When trying to add a new record to the database, the values from my two dropdownlists are not being included. All the other fields are indeed saving to the database.
I am passing a ViewModel to the view in question:
public class NewItemViewModel
{
public IEnumerable<Category> Categories { get; set; }
public Item Item { get; set; }
public IEnumerable<Donor> Donors { get; set; }
}
The domain models I am using:
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Quantity { get; set; }
public bool IsActive { get; set; }
public Category Category { get; set; }
public Donor Donor { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Donor
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
public string Email { get; set; }
}
The relevant controller: This New() action is simply used to pass data to the view for the form to be submitted
public ActionResult New()
{
var itemCategories = _context.ItemCategory.ToList();
var donors = _context.Donors.ToList();
var viewModel = new NewItemViewModel
{
Categories = itemCategories,
Donors = donors
};
return View(viewModel);
}
Here is my actual action that adds the submitted data to the database:
// Create a new item.
[HttpPost]
public ActionResult Create(Item item)
{
_context.Items.Add(item);
_context.SaveChanges();
return RedirectToAction("Index", "Item");
}
And lastly, the view itself (I will minimize the code here):
#using (Html.BeginForm("Create", "Item"))
{
<div class="form-group">
#Html.LabelFor(m => m.Item.Donor)
#Html.DropDownListFor(m => m.Item.Donor, new SelectList(Model.Donors, "Id", "FullName"), "Who donated this item?", new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.Item.Category)
#Html.DropDownListFor(m => m.Item.Category, new SelectList(Model.Categories, "Id", "Name"), "Select Item Category", new { #class = "form-control" })
</div>
}
To reiterate the problem I am having: The values of the dropdownlist for Category and Donor are not saving to the database, whereas the others (non-navigation properties?) Name, Description, Quantity, etc. is working correctly.
Am I using the ViewModel the right way? I was under the impression that the MVC framework knows how to deal with passing the Item object parameter in the Create() action - mapping what it needs to within the Item entity.
Any help would be much appreciated. Thank you.
In the NewItemViewModel you have not created property to hold the selected values from dropdown
public class NewItemViewModel
{
public IEnumerable<Category> Categories { get; set; }
public int SelectedCategory{get;set;}
public Item Item { get; set; }
public int SelectedDonor{get;set;}
public IEnumerable<Donor> Donors { get; set; }
}
#using (Html.BeginForm("Create", "Item"))
{
<div class="form-group">
#Html.LabelFor(m => m.Item.Donor)
#Html.DropDownListFor(m => m.SelectedDonor, new SelectList(Model.Donors, "Id", "FullName"), "Who donated this item?", new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.Item.Category)
#Html.DropDownListFor(m => m.SelectedCategory, new SelectList(Model.Categories, "Id", "Name"), "Select Item Category", new { #class = "form-control" })
</div>
}
I have a project model and a technology model. There can be multiple technologies in one project. There will be a limited amount of technology objects, around 5-10, that will be used across an unlimited amount of projects. I thought of keeping the technology items in an enum or just as constant variables, but I want the ability to add or edit down the road, so I figured I would put them in a table.
I tend to get hung up when dealing with lists. I want to be able to create a single project, and in the same view check a checkbox for the technology that was used on the project (ex. HTML5 or CSS3). I am not able to get a list of technologies to show up in the view for me to mark as checked for the particular project.
Project Class:
public class Project
{
public int Id { get; set; }
public string Website { get; set; }
public List<Technology> Technologies { get; set; }
}
Technology Class:
public class Technology
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
ViewModel:
public class ProjectTechnologyViewModel
{
public IEnumerable<Technology> Technologies { get; set; }
public Project Projects { get; set; }
public ProjectTechnologyViewModel()
{
Projects = new Project();
}
}
DbContext:
public class NovaDB : DbContext
{
public NovaDB(): base("DefaultConnection")
{
}
public DbSet<Technology> Technologies { get; set; }
public DbSet<Project> Projects{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Controller:
public ActionResult CreateProject()
{
return View();
}
[HttpPost]
public ActionResult CreateProject(ProjectTechnologyViewModel viewModel)
{
var proj = new Project();
if (ModelState.IsValid)
{
proj.LaunchDate = viewModel.Projects.LaunchDate;
proj.ProjectType = viewModel.Projects.ProjectType;
proj.ServiceId = viewModel.Projects.ServiceId;
proj.ShowInOurWork = viewModel.Projects.ShowInOurWork;
proj.Website = proj.Website;
proj.Technologies = new List<Technology>();
foreach (var t in viewModel.Technologies)
{
proj.Technologies.Add(new Technology()
{
Name = t.Name,
FAClassName = t.FAClassName,
IsActive = t.IsActive,
});
}
_db.Projects.AddOrUpdate(proj);
_db.SaveChanges();
}
return View(proj);
}
View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Project</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Projects.Website, htmlAttributes: new {#class = "control-label col-md-2"})
<div class="col-md-10">
#Html.EditorFor(model => model.Projects.Website, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.Projects.Website, "", new {#class = "text-danger"})
</div>
</div>
#for (int i = 0; i < Model.Technologies.Count(); i++)
{
#Html.CheckBoxFor(x=>x.Technologies[i].)
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Image of View:
The checkbox is for the IsActive property of the Technology, right? So, you can do this:
#Html.CheckBoxFor(model => model.Technologies.ToList()[i].IsActive) #Model.Technologies.ToList()[i].Name
You also need to instantiate your ViewModel and send it to your view in your GET action, like this:
public ActionResult CreateProject()
{
var model = new ProjectTechnologyViewModel();
model.Project = new Project();
model.Technologies = new List<Technology>();
return View(model);
}
Also, don't instantiate the properties in your ViewModel. Do that in your controller (see above):
public class ProjectTechnologyViewModel
{
public IEnumerable<Technology> Technologies { get; set; }
public Project Project { get; set; }
}
Why are you referring to a IEnumerable as an array?
this - someIEnumerable[0] will not be compiled.
Why don't you use foreach?
foreach(var i in Model.Technologies){
var a = i.Website;
}
Firstly, you will need a table to store the Technologies associated with a Project, (say ProjectTechnlogies) that will include FK fields to the Project ID field and the Technology ID field.
Then you will need view models to represent what your wanting to edit in the view
public class TechnologyVM
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; } // for binding to a checkbox
}
public class ProjectVM
{
public string Website { get; set; }
public IEnumerable<TechnologyVM> Technologies { get; set; }
}
and your GET method would be
public ActionResult Create()
{
ProjectVM model = new ProjectVM
{
Technologies = _db.Technologies.Where(t => t.IsActive).Select(t => new TechnologyVM
{
Id = t.Id,
Name = t.Name
})
};
return View(model);
}
Note I am assuming here that your IsActive property means that if the value is false its now an obsolete technology (it may have been assigned to previous Projects) and that you don't want to allow to to be selected in the view when creating a new Project.
Then create an EditorTemplate (partial) for TechnologyVM in /Views/Shared/EditorTemplates/TechnologyVM.cshtml (note the name of the file must match the name of the class)
#model TechnologyVM
<div>
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.Name) // if you want this value to be posted
#Html.CheckBoxFor(m => m.IsSelected)
#Html.LabelFor(m => m.IsSelected, Model.Name)
</div>
and the main view will be
#model ProjectVM
....
#using (Html.BeginForm())
{
....
#Html.TextBoxFor(m => m.Website)
....
#Html.EditorFor(m => m.Technologies)
<input type="submit" ... />
}
The EditorFor() method will correctly generate the html for each Technology
Finally you POST method will be
[HttpPost]
public ActionResult Create(ProjectVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}
Project project = new Project
{
Website = model.Website,
// ... other properties of Project
}
_db.Projects.Add(project);
_db.SaveChanges(); // The Project's Id property has now been set
IEnumerable<int> selectedTechnologies = model.Where(t => t.IsSelected).Select(t => t.Id);
foreach(int ID in selectedTechnologies)
{
ProjectTechnology technology = new ProjectTechnology
{
ProjectId = project.Id,
Technology = ID
};
_db.ProjectTechnologies.Add(technology);
}
_db.SaveChanges(); // save the project technologies
// redirect
}
I had to change a few models and I added a table to map the two models. I decided to save the "link" between the Project & Technology models in a shared table called ProjectTechnologyMap. For the project I create, I insert a record with the project Id and the Technology Id. The project Id stays constant and there are multiple technology Ids, depending on how many are selected in the view. I also save my project details to the project table. I do not save anything to the technology table as it is static (I do not create technologies on my Create Project View).
Here is my solution that worked:
Models:
public class Project
{
public int Id { get; set; }
public string Website { get; set; }
}
public class Technology
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
public class ProjectTechnologyMap
{
public int Id { get; set; }
public int ProjectId { get; set; }
public int TechnologyId { get; set; }
}
ViewModel:
public class ProjectTechnologyViewModel
{
public List<Technology> Technologies { get; set; }
public Project Projects { get; set; }
public ProjectTechnologyMap ProjectTechnologyMapping { get; set; }
public ProjectTechnologyViewModel()
{
Projects = new Project();
ProjectTechnologyMapping = new ProjectTechnologyMap();
}
}
DB Context:
public class NovaDB : DbContext
{
public NovaDB(): base("DefaultConnection")
{
}
public DbSet<Technology> Technologies { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<ProjectTechnologyMap> ProjectTechnologyMappings { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Controller:
public ActionResult Create()
{
var technologies = from t in _db.Technologies
orderby t.Name
where t.IsActive
select t;
var viewModel = new ProjectTechnologyViewModel();
viewModel.Technologies = technologies.ToList();
return View(viewModel);
}
[HttpPost]
public ActionResult Create(ProjectTechnologyViewModel viewModel)
{
if (ModelState.IsValid)
{
var proj = new Project
{
LaunchDate = viewModel.Projects.LaunchDate,
ProjectType = viewModel.Projects.ProjectType,
ServiceId = viewModel.Projects.ServiceId,
ShowInOurWork = viewModel.Projects.ShowInOurWork,
Website = viewModel.Projects.Website
};
_db.Projects.AddOrUpdate(proj);
_db.SaveChanges();
var map = new ProjectTechnologyMap();
foreach (var item in viewModel.Technologies)
{
if (item.UsedInProject)
{
map.TechnologyId = item.Id;
map.ProjectId = proj.Id;
_db.ProjectTechnologyMappings.Add(map);
_db.SaveChanges();
}
}
}
return RedirectToAction("Index", "Project");
}
Loop in my View to handle the list of technologies:
#for (var i = 0; i < Model.Technologies.Count; i++)
{
<div class="form-group">
#Html.LabelFor(x => x.Technologies[i].Name, Model.Technologies[i].Name, new {#class = "control-label col-md-2"})
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(x => x.Technologies[i].UsedInProject)
#Html.HiddenFor(x => x.Technologies[i].Id)
</div>
</div>
</div>
}
I am new to MVC and would appreciate any advice. I have several models/tables that work together. The trouble I am having is with a many-to-many relationship. What I want is to have a listbox that a user can multiselect from and pass those values to save in join table, while saving the primary entry to another table.
My models:
public class Card
{
public virtual int CardID { get; set; }
public virtual string Title { get; set; }
//A bunch of properties...
//Drop Down Lists
public int RarityID { get; set; }
public virtual Rarity Rarity { get; set; }
public int MainTypeID { get; set; }
public virtual MainType MainType { get; set; }
public int CardSetID { get; set; }
public virtual CardSet CardSet { get; set; }
public int SubTypeID { get; set; }
public virtual SubType SubType { get; set; }
public virtual string AdditionalType { get; set; }
public virtual IList<CardAbility> Abilities { get; set; }
public virtual int[] SelectedAbilities { get; set; }
}
public class Ability
{
public virtual int AbilityID { get; set; }
public virtual string Title { get; set; }
public virtual IList<CardAbility> Cards { get; set; }
}
public class CardAbility
{
public int CardAbilityID { get; set; }
public virtual Ability Ability { get; set; }
public int AbilityID { get; set; }
public virtual Card Card { get; set; }
public int CardID { get; set; }
}
My Controller:
public ActionResult Create()
{
ViewBag.RarityID = new SelectList(db.Rarities, "RarityID", "Title");
ViewBag.MainTypeID = new SelectList(db.MainTypes, "MainTypeID", "Title");
ViewBag.CardSetID = new SelectList(db.CardSets, "CardSetID", "Title");
ViewBag.SubTypeID = new SelectList(db.SubTypes, "SubTypeID", "Title");
ViewBag.Abilities = new MultiSelectList(db.Abilities, "AbilityID", "Title");
return View();
}
// POST: /Card/Create
[HttpPost]
public ActionResult Create(Card card)
//[ModelBinder(typeof(CardBinder1))]
{
if (ModelState.IsValid)
{
db.Cards.Add(card);
db.SaveChanges();
foreach (var items in card.SelectedAbilities)
{
var obj = new CardAbility() { AbilityID = items, CardID = card.CardID };
db.CardAbilities.Add(obj);
}
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.RarityID = new SelectList(db.Rarities, "RarityID", "Title", card.RarityID);
ViewBag.MainTypeID = new SelectList(db.MainTypes, "MainTypeID", "Title", card.MainTypeID);
ViewBag.CardSetID = new SelectList(db.CardSets, "CardSetID", "Title", card.CardSetID);
ViewBag.SubTypeID = new SelectList(db.SubTypes, "SubTypeID", "Title", card.SubTypeID);
ViewBag.Abilities = new MultiSelectList(db.Abilities, "AbilityID", "Title");
return View(card);
My Create View:
model MTG.Models.Card
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Card</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.Label("Abilities")
</div>
<div class="editor-field">
#Html.ListBoxFor(model => model.Abilities, (ViewBag.AbilityID as MultiSelectList))
#Html.ValidationMessageFor(model => model.Abilities)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.RarityID, "Rarity")
</div>
<div class="editor-field">
#Html.DropDownList("RarityID", String.Empty)
#Html.ValidationMessageFor(model => model.RarityID)
</div>
// A lot more fields...
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
My DBContext:
public DbSet<Ability> Abilities { get; set; }
public DbSet<Rarity> Rarities { get; set; }
public DbSet<CardSet> CardSets { get; set; }
public DbSet<MainType> MainTypes { get; set; }
public DbSet<SubType> SubTypes { get; set; }
public DbSet<Card> Cards { get; set; }
public DbSet<CardAbility> CardAbilities { get; set; }
public class AbilitiesToCardsConfiguration : EntityTypeConfiguration<CardAbility>
{
internal AbilitiesToCardsConfiguration()
{
this.HasKey(p => new { p.AbilityID, p.CardID });
this.HasRequired(p => p.Ability)
.WithMany(p => p.Cards)
.HasForeignKey(p => p.AbilityID);
this.HasRequired(p => p.Card)
.WithMany(r => r.Abilities)
.HasForeignKey(p => p.CardID);
}
}
I have been working on this for about 3 days and have done a lot of trial and error from what I have read online. At this point, the create view does display a listbox that is pulling the titles from the Abilities table. When I try to save, I get a validation error "The value "1" is invalid.", where 1 is the ID for that ability. When debugging, I see that the modelstate is invalid and the error is
{System.InvalidOperationException: The parameter conversion from type 'System.String' to type 'MTG.Models.CardAbility' failed because no type converter can convert between these types.
at System.Web.Mvc.ValueProviderResult.ConvertSimpleType(CultureInfo culture, Object value, Type destinationType)
at System.Web.Mvc.ValueProviderResult.UnwrapPossibleArrayType(CultureInfo culture, Object value, Type destinationType)
at System.Web.Mvc.ValueProviderResult.ConvertTo(Type type, CultureInfo culture)
at System.Web.Mvc.DefaultModelBinder.ConvertProviderResult(ModelStateDictionary modelState, String modelStateKey, ValueProviderResult valueProviderResult, Type destinationType)}
I know it doesn't like the types and can't convert, but if I try anything else with the listboxfor helper it won't bring in the data and usually crashes before I even get to see the create page. Sorry this is so long, I just wanted to give all the information I could. :) Thank you for any help.
Generate a listbox for SelectedAbilities instead of Abilities:
#Html.ListBoxFor(model => model.SelectedAbilities , (ViewBag.AbilityID as MultiSelectList))
By the way you need to do the same for RarityID instead of Rarity, MainTypeID instead of MainType and etc.
Although this error is very common in the forum, but i am not able to understand how to fix it in my project. I am new to MVC framework.
View code:-
#model ClassifiedProject.Models.CreateAdvertVM
<div class="editor-label">#Html.LabelFor(model => model.AdvTitle) <i>(E.g. Old Samsung Galaxy Tab 2)</i></div>
<div class="editor-field">
#Html.EditorFor(model => model.AdvTitle)
#Html.ValidationMessageFor(model => model.AdvTitle)
</div>
<div class="editor-label">#Html.LabelFor(model => model.AdvDescription)</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.AdvDescription)
#Html.ValidationMessageFor(model => model.AdvDescription)
</div>
<div class="editor-label">#Html.Label("Advertisement Category")</div>
<div class="editor-label">
#Html.DropDownListFor(model => model.SelectedCategoryId, Model.Categories, new { #class = "ddlcs" })
#Html.ValidationMessageFor(model => model.SelectedCategoryId)
</div>
<p><input type="submit" value="Save" /></p>
Controller code of Save button actionresult:-
[HttpPost]
public ActionResult Create(TR_ADVERTISEMENT tr_advert)
{
if (ModelState.IsValid)
{
tr_advert.CreatedDate = tr_advert.ModifiedDate = DateTime.Now;
if (tr_advert.IsPriceOnRequest)
{
tr_advert.CurrencyID = 0;
tr_advert.Price = 0;
}
db.ADVERTISEMENT.Add(tr_advert);
db.SaveChanges();
return RedirectToAction("Index");
}
Controller code for the form in render stage:-
// GET: /Advert/Create
public ActionResult Create()
{
var model = new CreateAdvertVM();
ViewBag.Message = "Post New Advertisement.";
////Render Category DDL
var cat = from s in db.CategoryDbSet
where s.IsActive == true
orderby s.CatName
select new { s.CatID, s.CatName };
var catListItems = cat.ToList().Select(c => new SelectListItem
{
Text = c.CatName,
Value = c.CatID.ToString()
}).ToList();
catListItems.Insert(0, new SelectListItem { Text = "[--Select the category--]", Value = "" });
model.Categories = catListItems;
return View(model);
ViewModel inherited from EF class:-
[NotMapped]
public class CreateAdvertVM : TR_ADVERTISEMENT
{
[DisplayName("Category")]
[Required]
public int? SelectedCategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
}
EF Model:-
public class TR_ADVERTISEMENT
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AdvID { get; set; }
[Required]
[DisplayName("Sub Category")]
public int SubCatID { get; set; }
public int CurrencyID { get; set; }
[DisplayName("Price on request")]
public bool IsPriceOnRequest { get; set; }
[DisplayName("Posted Date")]
[DisplayFormat (DataFormatString="{0:dd-MM-yyyy}")]
public Nullable<System.DateTime> CreatedDate { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
}
On the save button click, i have to save the data into the tr_advertisement table using the EF model.
Please suggest the solution to this problem.
It is the model type you are passing into your Create ActionMethod.
public ActionResult Create(TR_ADVERTISEMENT tr_advert)
should be
public ActionResult Create(CreateAdvertVM tr_advert)
I am assuming that if your model is not valid, you are passing it back further down in your action result (which you are not showing), such as
Return View(tr_advert)
But, you are passing the wrong model type at that point for that view.
EDIT
I would also update your view model so that instead of inheriting from the EF class, simply include the EF class as a property.
public class CreateAdvertVM
{
[DisplayName("Category")]
[Required]
public int? SelectedCategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public TR_ADVERTISEMENT tr_advert{get;set;}
}
This will make it so that your save code in the Create method can still be used with only minor modifications
[HttpPost]
public ActionResult Create(CreateAdvertVM model)
{
if (ModelState.IsValid)
{
model.tr_advert.CreatedDate = model.tr_advert.ModifiedDate = DateTime.Now;
if (model.tr_advert.IsPriceOnRequest)
{
model.tr_advert.CurrencyID = 0;
model.tr_advert.Price = 0;
}
db.ADVERTISEMENT.Add(model.tr_advert);
db.SaveChanges();
return RedirectToAction("Index");
}
public class Movies
{
[Key]
public int movieID { get; set; }
public String Title { get; set; }
public virtual Genres parentGenre { get; set; }
}
public class Genres
{
public Genres()
{
this.movies = new HashSet<Movies>();
}
[Key]
public int genreId { get; set; }
public String genreName { get; set; }
public ICollection<Movies> movies { get; set; }
}
I can successfully create a DropDownList on my addmovie view page by reading in the Genres table.
But when I try submit the page, it states "The value '10' is invalid." This leads me to believe that I am trying to put an Int (from the dropdownlist value) into an object (from the "Genres parentGenre").
Have I set up the "Genres parentGenre" to "genreId" foreign key relationship correctly to where it should only want a 'number' for the "parentGenre" field, or does it expect more?
added:
controller:
[HttpPost]
public ActionResult Create(Movies movies)
{
if (ModelState.IsValid)
{
db.Movies.Add(movies);
db.SaveChanges();
return RedirectToAction("Index");
}
IEnumerable<SelectListItem> items = db.Genres
.Select(c => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)c.genreId).Trim(),
Text = c.genreName
});
ViewBag.genreId = items;
}
view:
<div class="editor-label">
#Html.LabelFor(model => model.parentGenre.genreName)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.parentGenre,(IEnumerable<SelectListItem>)ViewBag.genreId)
#Html.ValidationMessageFor(model => model.parentGenre)
In lieu of your comments, here's what I'd recommend:
Models:
public class Movie
{
[Key]
public int MovieID { get; set; }
public String Title { get; set; }
public int GenreId { get; set; }
public virtual Genre Genre { get; set; }
}
public class Genre
{
public Genre()
{
this.movies = new HashSet<Movies>();
}
[Key]
public int GenreId { get; set; }
public String Name { get; set; }
public ICollection<Movies> Movies { get; set; }
}
Controller:
[HttpPost]
public ActionResult Create(Movie Movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(Movie);
db.SaveChanges();
return RedirectToAction("Index");
}
IEnumerable<SelectListItem> items = db.Genres
.Select(c => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)c.GenreId).Trim(),
Text = c.Name
});
ViewBag.genreId = items;
}
View:
<div class="editor-label">
#Html.LabelFor(model => model.Genre.Name)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Genre.Id,(IEnumerable<SelectListItem>)ViewBag.genreId)
#Html.ValidationMessageFor(model => model.Genre)
</div>
If I'm reading what you're doing correctly, that should work. I haven't done much with EF though, so I can't be 100% certain.