ViewModel,带有一个SelectList和一个带有单个记录的LINQ查询结果
本文关键字:记录 单个 LINQ 结果 查询 一个 SelectList 有一个 ViewModel | 更新日期: 2023-09-27 18:14:47
我们如何用以下两个属性填充ViewModel:
- LINQ查询中只返回一条记录的
query result type
- A
SelectList
型
换句话说,假设我们有一个基于所选ID只显示单个电影的视图。我们想分配一年的发布,从年的下拉列表的电影,我如何在以下视图模型和控制器中填写????
?
注意:在以下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;}
}
ViewModel
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);
}
在我的实际项目中,模型有很多属性,相应的View也显示了这些属性中的大部分。我在想是否有一种更简单的方法来定义一个ViewModel,它不包含模型的所有属性,比如这个ASP。NET文章定义了一个视图模型MovieGenreViewModel
,但在那里他们使用列表,并在他们的视图中迭代多个电影。我试图模仿他们的例子,但在我的情况下,这是一个单一的记录(不是记录列表)与SelectList
。我如何用一条记录模拟那种场景,而不能在视图模型中包含模型所具有的大量模型属性?
因为你想要更新一个Movie记录,所有你需要得到的电影记录是它的唯一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语句返回一个元素的集合。不能将Movies集合分配给Movie类型的属性。你可以使用FirstOrDefault()方法来获取单个对象。
var movie = _context.Movies.FirstOrDefault(x=>x.ID==movieID);
//After null check
vm.Movie = movie;
为什么不能使用Movie作为myMovie属性的类型?然后,您可以使用该对象来显示名称。即 movie.Name 。您还可以将movieId存储在一个隐藏字段中,以便在您发回时可以在服务器端使用它。您可以使用LINQ从数据库检索该对象,如下所示:
var qrysingleMovie = _context.Movies.Single(m=> m.ID == movieID);
或者你可以使用2个属性而不是整个对象。一个用于标题,即:string MovieName,另一个用于id, int MovieId
public string MovieName { get; set; }
public int MovieId { get; set; }
注意:记住,使用"Single"意味着你需要在数据库中有电影,否则它会抛出异常。