Reputation: 2028
Something very simple but I am looking for the best way to do it. I have a Movie entity, each Movie can be in one Language only(a lookup table with English, French,etc...). Now I'm trying to load all the available languages in the lookup in the Movie Create Page, the Movie View Model:
namespace Project.ViewModels {
public class Movie {
[Key]
public int ID { get; set; }
public string Title { get; set; }
public string Rating { get; set; }
public string Director { get; set; }
public string Plot { get; set; }
public string Link { get; set; }
public string Starring { get; set; }
public int DateCreated { get; set; }
public string Genre { get; set; }
[Display(Name = "Language")]
public int LanguageID { get; set; }
// Navigational Properties
public virtual MovieLanguage Language { get; set; }
}
}
The MovieLanguage View model:
namespace MAKANI.ViewModels {
public class MovieLanguage {
[Key]
public int ID { get; set; }
public string Language { get; set; }
public virtual ICollection<Movie> Movies { get; set; }
}
}
The controller action:
public ActionResult MovieCreate() {
using (MAKANI.Models.Entities db = new MAKANI.Models.Entities()) {
List<Models.MoviesLanguages> enLanguages = db.MoviesLanguages.ToList();
IEnumerable<SelectListItem> selectList =
from m in enLanguages
select new SelectListItem {
Text = m.Language,
Value = m.ID.ToString()
};
ViewBag.SelectLanguage = selectList.ToList();
return View();
}
}
And in the View page i have
<div class="editor-field">
@Html.DropDownList("Language", ViewBag.SelectLanguage);
</div>
Howver I am getting this error in the View: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'DropDownList' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax
Not sure what the problem might be?
Another questions regarding this approach:
Upvotes: 0
Views: 1109
Reputation: 218942
Have a Languages
Collection Property in your Movie
ViewModel and a SelectedLanguage Property to get the selected Language ID when the form submits. It is not necessary that your ViewModel should have all the properties like your domain model. Have only those properties which the View needs.
public class Movie
{
public int ID { set;get;}
public string Title { set;get;}
//Other Relevant Properties also.
public IEnumerable<SelectListItem> Languages { set;get;}
public int SelectedLanguage { set;get;}
public Movie()
{
Languages =new List<SelectListItem>();
}
}
Now in your GET
Action, Create an object of your Movie
ViewModel and set the Languages Collection property and send that to the View. Try to avoid using ViewBag for passing data like this. ViewBag
makes our code dirty.Why not use the strongly typed ViewModels to its full extent ?
public ActionResult CreateMovie()
{
var vm=new Movie();
// TO DO : I recommend you to abstract code to get the languages from DB
// to a different method so that your action methods will be
// skinny and that method can be called in different places.
var enLanguages = db.MoviesLanguages.ToList();
vm.Languages= = from m in enLanguages
select new SelectListItem {
Text = m.Language,
Value = m.ID.ToString()
};
return View(vm);
}
And in your view which is strongly typed to our Movie
ViewModel, use the DropDownListFor Hemml helper method
@model Movie
@using(Html.Beginform())
{
@Html.DropDownListFor(x => x.SelectedLanguage,
new SelectList(Model.Languages, "Value", "Text"), "Select Language")
<input type="submit" />
}
Now when you post the form, you will get the selected languageId in the SelectedLanguage
Property of your ViewModel
[HttpPost]
public ActionResult CreateMovie(Movie model)
{
If(ModelState.IsValid)
{
//check model.SelectedLanguage property here.
//Save and Redirect (PRG pattern)
}
//you need to reload the languages here again because HTTP is stateless.
return View(model);
}
Upvotes: 1