我们如何使用以下两个属性填充ViewModel:
query result type
仅返回单个记录SelectList
类型换句话说,假设我们有一个视图,根据所选ID只显示一部电影。我们希望从下拉列表中为该电影分配一年的发布时间,如何填写以下ViewModel和Controller中的????
?
注意:在以下ViewModel中,如果我使用类型为IQueryable<Movie>
的myMovie属性,并将ViewModel的此属性分配给来自跟随控制器的查询qrySingleMovie,则会收到错误the name qrySingleMovie does not exist in the current context
模型
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
public class Year
{
public int YearId {get; set;}
public int MovieYear {get; set;}
}
视图模型
public class MovieGenreViewModel
{
public ???? myMovie;
public SelectList MovieReleaseYears;
public int ReleasedYr { get; set; }
}
控制器
public async Task<IActionResult> Index(int MovieID)
{
// Use LINQ to get list of Release years.
IQueryable<string> YearQuery = from m in _context.Years
orderby m.MovieYear
select m.MovieYear;
//Following query selects only a single movie based on Primary Key ID
var qrysingleMovie = from m in _context.Movies
where m.ID == movieID
select m;
var movieReleaseYrVM = new MovieGenreViewModel();
movieReleaseYrVM.MovieReleaseYears = new SelectList(await YearQuery.ToListAsync());
movieReleaseYrVM.myMovie = ????
return View(movieReleaseYrVM);
}
更新
在我的真实项目中,模型具有许多属性,相应的视图也会显示大部分属性。我在想是否有一种更简单的方法来定义一个不包含模型所有属性的ViewModel,例如ASP.NET Article定义了一个视图模型MovieGenreViewModel
但是他们在他们的视图中使用了List他们正在迭代多部电影。我试图模仿他们的例子但在我的情况下,它是一个SelectList
的单个记录(不是记录列表)。如何使用单个记录模拟这种情况,并且无法在View Model中包含大量模型属性?
答案 0 :(得分:1)
由于您想要更新电影记录,获取电影记录所需的只是它的唯一ID。那么为什么不将MovieId属性添加到视图模型中呢?如果您希望在UI中显示MovieName,也可以添加MovieName
属性。
请记住视图模型特定于视图。创建视图模型时,无需模拟整个实体模型。只添加您的视图绝对需要的属性。
public class MovieGenreViewModel
{
public int MovieId;
public string MovieName { set;get;}
public SelectList MovieReleaseYears;
public int ReleasedYr { get; set; }
}
现在,在您的GET操作中设置这些属性值。
public async Task<IActionResult> Index(int MovieID)
{
var vm = new MovieGenreViewModel();
var movie = _context.Movies.FirstOrDefault(x=>x.ID==movieID);
if(movie==null)
return Content("Movie not found"); // to do :Return a view with "not found" message
IQueryable<string> YearQuery = from m in _context.Years
orderby m.MovieYear
select m.MovieYear;
// set the property values.
vm .MovieReleaseYears = new SelectList(await YearQuery.ToListAsync());
vm .MovieId= movie.ID;
vm .MovieName= movie.Name;
return View(vm );
}
现在在您的视图中,您将影片ID保存在隐藏字段中,这样当您提交表单时,它将被提交给处理表单提交的HttpPost操作方法。
@model MovieGenreViewModel
@using(Html.BeginForm("AssignYear","Home"))
{
<p>@Model.MovieName</p>
@Html.HiddenFor(s=>s.MovieId)
@Html.DropDownListFor(d=>d.ReleasedYr, Model.MovieReleaseYears)
<input type="submit"/>
}
您可以使用与AssignYear
操作方法参数
[HttpPost]
public ActionResult AssignYear(MovieGenreViewModel model)
{
// check model.MovieId and model.ReleasedYr
// to do : Save data and return something
}
如果您不希望仅将视图所需的属性添加到视图模型,但希望显示电影的大量属性,则可以考虑向您的类型添加Movie
类型的新属性查看模型
public class MovieGenreViewModel
{
public Movie Movie { set;get;}
public SelectList MovieReleaseYears;
public int ReleasedYr { get; set; }
}
您现有的LINQ语句返回一个元素的集合。您无法将电影集合分配给Movie类型的属性。您可以使用FirstOrDefault()方法获取单个对象。
var movie = _context.Movies.FirstOrDefault(x=>x.ID==movieID);
//After null check
vm.Movie = movie;
答案 1 :(得分:0)
为什么不能将Movie用作“myMovie”属性的类型? 然后,您可以使用该对象显示example.ie movie.Name 的名称。 您还可以将movieId存储在隐藏字段中,这样当您回发时,它将可供您在服务器端使用。 您可以使用LINQ从数据库中检索该对象,如下所示:
var qrysingleMovie = _context.Movies.Single(m=> m.ID == movieID);
或者,您可以使用2个属性而不是整个对象。一个用于标题,即:字符串MovieName,另一个用于id int MovieId
public string MovieName { get; set; }
public int MovieId { get; set; }
注意:请记住,使用“Single”意味着您需要在数据库中放置电影,否则会引发异常。