带有 SelectList 的 ViewModel 和带有单个记录的 LINQ 查询结果
ViewModel with a SelectList and a LINQ Query result with a single reocrd
我们如何使用以下两个属性填充 ViewModel:
- 来自 LINQ 查询的
query result type
returns 只有一条记录
- 一个
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;}
}
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 Article 定义了一个视图模型 MovieGenreViewModel
但他们正在使用 List 并在他们的 View他们正在遍历多部电影。我试图模仿他们的示例,但在我的例子中,它是带有 SelectList
的单个记录(不是记录列表)。我怎样才能用一条记录模拟这种场景,而不能在视图模型中包含该模型具有的大量模型属性?
既然你想更新一个电影记录,你只需要获取电影记录的唯一ID。那么为什么不将 MovieId 属性 添加到您的视图模型。如果您希望在 UI 中显示电影名称,您也可以添加 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 语句 returns 一个元素的集合。您不能将电影集合分配给 属性 类型的电影。您可以使用 FirstOrDefault() 方法获取单个对象。
var movie = _context.Movies.FirstOrDefault(x=>x.ID==movieID);
//After null check
vm.Movie = movie;
为什么不能使用 Movie 作为 "myMovie" 属性 的类型?
然后您可以使用 object 来显示 example.ie movie.Name 的名称。
您还可以将 movieId 存储在隐藏字段中,这样当您 post 返回时,您可以在服务器端使用它。
您可以使用 LINQ 从数据库中检索 object,如下所示:
var qrysingleMovie = _context.Movies.Single(m=> m.ID == movieID);
或者,您可以使用 2 个属性而不是整个 object。一个用于标题,即:string MovieName,另一个用于 id int MovieId
public string MovieName { get; set; }
public int MovieId { get; set; }
注意:请记住,使用 "Single" 意味着您需要在数据库中拥有电影,否则会抛出异常。
我们如何使用以下两个属性填充 ViewModel:
- 来自 LINQ 查询的
query result type
returns 只有一条记录 - 一个
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;}
}
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 Article 定义了一个视图模型 MovieGenreViewModel
但他们正在使用 List 并在他们的 View他们正在遍历多部电影。我试图模仿他们的示例,但在我的例子中,它是带有 SelectList
的单个记录(不是记录列表)。我怎样才能用一条记录模拟这种场景,而不能在视图模型中包含该模型具有的大量模型属性?
既然你想更新一个电影记录,你只需要获取电影记录的唯一ID。那么为什么不将 MovieId 属性 添加到您的视图模型。如果您希望在 UI 中显示电影名称,您也可以添加 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 语句 returns 一个元素的集合。您不能将电影集合分配给 属性 类型的电影。您可以使用 FirstOrDefault() 方法获取单个对象。
var movie = _context.Movies.FirstOrDefault(x=>x.ID==movieID);
//After null check
vm.Movie = movie;
为什么不能使用 Movie 作为 "myMovie" 属性 的类型? 然后您可以使用 object 来显示 example.ie movie.Name 的名称。 您还可以将 movieId 存储在隐藏字段中,这样当您 post 返回时,您可以在服务器端使用它。 您可以使用 LINQ 从数据库中检索 object,如下所示:
var qrysingleMovie = _context.Movies.Single(m=> m.ID == movieID);
或者,您可以使用 2 个属性而不是整个 object。一个用于标题,即:string MovieName,另一个用于 id int MovieId
public string MovieName { get; set; }
public int MovieId { get; set; }
注意:请记住,使用 "Single" 意味着您需要在数据库中拥有电影,否则会抛出异常。