在ASP.net MVC中加载相关数据

时间:2012-09-04 12:37:05

标签: asp.net asp.net-mvc entity-framework

非常简单,但我正在寻找最好的方法。我有一个Movie实体,每个Movie只能使用一种语言(一个包含英语,法语等的查找表...)。现在我正在尝试在电影创建页面,电影视图模型中查找所有可用的语言:

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; }
    }
}

MovieLanguage View模型:

namespace MAKANI.ViewModels {
    public class MovieLanguage {

        [Key]
        public int ID { get; set; }

        public string Language { get; set; }

        public virtual ICollection<Movie> Movies { get; set; }
    }
}

控制器操作:

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();
    }          
}

在View页面中我有

    <div class="editor-field">
        @Html.DropDownList("Language", ViewBag.SelectLanguage);            
    </div>

如果我在视图中收到此错误: 'System.Web.Mvc.HtmlHelper'没有名为'DropDownList'的适用方法,但似乎有一个名称的扩展方法。无法动态分派扩展方法。考虑转换动态参数或调用扩展方法而不使用扩展方法语法

不确定问题可能是什么?

关于这种方法的另一个问题:

  • 首先应该为MovieLanguage实体创建一个视图模型,知道它只作为查找表服务(所以它不需要任何创建/编辑/删除操作,只有List / Read可能),我应该是在这种情况下直接取决于EF实体?

1 个答案:

答案 0 :(得分:1)

Languages ViewModel和SelectedLanguage属性中设置Movie集合属性,以便在表单提交时获取所选的语言ID。您的ViewModel不必具有域模型等所有属性。 只拥有View所需的属性。

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>();
  }
}

现在,在GET操作中,创建Movie ViewModel的对象,并设置Languages Collection属性并将其发送到View。尝试avoid使用ViewBag传递这样的数据。 ViewBag使我们的代码变脏。为什么不使用强类型的ViewModel到它的全部范围?

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);
}

在您的视图中,我们的Movie ViewModel是强类型的,请使用DropDownListFor Hemml辅助方法

@model Movie
@using(Html.Beginform())
{
    @Html.DropDownListFor(x => x.SelectedLanguage, 
            new SelectList(Model.Languages, "Value", "Text"), "Select Language")
   <input type="submit" />
}

现在,当您发布表单时,您将在ViewModel的SelectedLanguage属性中获取所选的languageId

[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);
}