【发布时间】:2018-04-30 07:10:27
【问题描述】:
我正在尝试制作一个在一个视图(ASP.NET Core + MVC + Entity Framework)中具有父子模型(多个模型)的 Web 应用程序。
以下是输入(输入No.1)。 这是“视图/博客/index.cshtml”
以下也被输入(输入No.2)。 这是“视图/标签/index.cshtml”
以下是我期望的输出(输出 No.1)。
我写了以下“视图/博客/cshtml”。
@model IEnumerable<urlapp12.Models.UrlTag>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Blog.Userid)
</th>
<th>
@Html.DisplayNameFor(model => model.Blog.Url)
</th>
<th>
@Html.DisplayNameFor(model => model.Blog.LastUpdatedAt_UtcDt)
</th>
<th>
@Html.DisplayNameFor(model => model.Blog.LastUpdatedAt_LocalDt)
</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Blog.Userid)
</td>
<td>
<a href="@Html.DisplayFor(modelItem => item.Blog.Url)">@Html.DisplayFor(modelItem => item.Blog.Title)</a>
</td>
<td>
@Html.DisplayFor(modelItem => item.Blog.LastUpdatedAt_UtcDt)
</td>
<td>
@Html.DisplayFor(modelItem => item.Blog.LastUpdatedAt_LocalDt)
</td>
<td>
@foreach (var childItem in item.Tag)
{
@Html.DisplayFor(modelItem => childItem.tagItem)
}
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.Blog.BlogId">Edit</a> |
<a asp-action="Details" asp-route-id="@item.Blog.BlogId">Details</a> |
<a asp-action="Delete" asp-route-id="@item.Blog.BlogId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
并执行,我收到以下错误。 (输出 No.2。真正的意外输出)
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[urlapp12.Models.Blog]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable`1[urlapp12.Models.UrlTag]'.
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(object value)
Models/Blog.cs 如下。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace urlapp12.Models
{
public partial class Blog
{
public Blog()
{
Post = new HashSet<Post>();
}
[Key]
public int BlogId { get; set; }
public string Userid { get; set; }
public string Url { get; set; }
public string Title { get; set; }
public string CreatedBy { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime CreatedAt_UtcDt { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime CreatedAt_LocalDt { get; set; }
public string LastUpdatedBy { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime LastUpdatedAt_UtcDt { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime LastUpdatedAt_LocalDt { get; set; }
public ICollection<Tag> Tag { get; set; }
public ICollection<Post> Post { get; set; }
/*
public List<Tag> Tag { get; set; }
public List<Post> Post { get; set; }
*/
}
}
Models/Tag.cs 如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace urlapp12.Models
{
public class Tag
{
public int Id { get; set; }
public int DispOrderNbr { get; set; }
public string tagItem { get; set; }
public int BlogId { get; set; }
public string CreatedBy { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime CreatedAt_UtcDt { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime CreatedAt_LocalDt { get; set; }
public string LastUpdatedBy { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime LastUpdatedAt_UtcDt { get; set; }
[System.ComponentModel.DataAnnotations.Schema.Column(TypeName = "datetime2")]
public DateTime LastUpdatedAt_LocalDt { get; set; }
[System.ComponentModel.DataAnnotations.Schema.ForeignKey("BlogId")]
public Blog blog { get; set; }
}
}
Model/UlrTag.cs 如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace urlapp12.Models
{
public class UrlTag
{
public Blog Blog { get; set; }
public IEnumerable<Tag> Tag { get; set; }
}
}
有人对这个父子模型有帮助吗? 提前谢谢你。
Blogs.Controller.cs 如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using urlapp12.Models;
namespace urlapp12.Controllers
{
public class BlogsController : Controller
{
private readonly Blogging02Context _context;
// Stores UserManager
private readonly UserManager<ApplicationUser> _manager;
private UserManager<ApplicationUser> _userManager;
public BlogsController(Blogging02Context context, UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
_context = context;
}
// GET: Blogs
public async Task<IActionResult> Index()
{
return View(await _context.Blog.ToListAsync());
}
// GET: Blogs/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var blog = await _context.Blog
.SingleOrDefaultAsync(m => m.BlogId == id);
if (blog == null)
{
return NotFound();
}
return View(blog);
}
// GET: Blogs/Create
public IActionResult Create()
{
return View();
}
// POST: Blogs/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost] [ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("BlogId,Userid,Url,Title")] Blog blog)
{
if (ModelState.IsValid)
{
/*
string strCurrentUserId;
strCurrentUserId = User.Identity.GetUserId(this IIdentity identity);
var currentUserName = User.Identity.Name ;
var user = await UserManager<ApplicationUser>.FindByIdAsync(User.Identity.GetUserId());
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));
var UserManager = new UserManager(IUserstore<ApplicationUser>);
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
var user = await GetCurrentUserAsync();
var userId = user?.Id;
string mail = user?.Email;
var userid = GetCurrentUserClaims().userid;
var userClaims = new UserClaims();
var claims = _httpContextAccessor.HttpContext.User.Claims.ToList();
var userid2 = await IGenericRepository < User > userRepository.GetByIdAsync(_currentUserGuid);
UserManager<ApplicationUser> _userManager;
SignInManager<ApplicationUser> _signInManager = new SignInManager<ApplicationUser>();
var info = await _signInManager.GetExternalLoginInfoAsync();
*/
// Stores UserManager
// private readonly UserManager<ApplicationUser> _manager;
// var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
// var result = await _userManager.CreateAsync(user, model.Password);
var user = await _userManager.GetUserAsync(HttpContext.User);
var currentLoginUserid = user.Id;
blog.Userid = user.Id;
int maxIdInDb = 0;
int BlogRecCnt = _context.Blog.Count();
if (_context.Blog.Count() == 0)
{
maxIdInDb = 0;
}
else
{
maxIdInDb = _context.Blog.Max(p => p.BlogId);
}
int NextId = maxIdInDb + 1;
blog.BlogId = NextId;
blog.CreatedAt_LocalDt = DateTime.Now;
blog.CreatedAt_UtcDt = DateTime.UtcNow;
blog.CreatedBy = user.Id;
blog.LastUpdatedAt_LocalDt = DateTime.Now;
blog.LastUpdatedAt_UtcDt = DateTime.UtcNow;
blog.LastUpdatedBy = user.Id;
_context.Add(blog);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(blog);
}
// GET: Blogs/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var blog = await _context.Blog.SingleOrDefaultAsync(m => m.BlogId == id);
if (blog == null)
{
return NotFound();
}
var user = await _userManager.GetUserAsync(HttpContext.User);
var currentLoginUserid = user.Id;
blog.Userid = user.Id;
blog.LastUpdatedAt_LocalDt = DateTime.Now;
blog.LastUpdatedAt_UtcDt = DateTime.UtcNow;
blog.LastUpdatedBy = user.Id;
return View(blog);
}
// POST: Blogs/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("BlogId,Userid,Url,Title")] Blog blog)
{
if (id != blog.BlogId)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(blog);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!BlogExists(blog.BlogId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(blog);
}
// GET: Blogs/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var blog = await _context.Blog
.SingleOrDefaultAsync(m => m.BlogId == id);
if (blog == null)
{
return NotFound();
}
return View(blog);
}
// POST: Blogs/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var blog = await _context.Blog.SingleOrDefaultAsync(m => m.BlogId == id);
_context.Blog.Remove(blog);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool BlogExists(int id)
{
return _context.Blog.Any(e => e.BlogId == id);
}
}
}
TagsController.cs 如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using urlapp12.Models;
namespace urlapp12.Controllers
{
public class TagsController : Controller
{
private readonly Blogging02Context _context;
public TagsController(Blogging02Context context)
{
_context = context;
}
//int id, [Bind("BlogId,Userid,Url,Title")] Blog blog
// GET: Tags
// public async Task<IActionResult> Index()
public async Task<IActionResult> Index(int id, [Bind("BlogId,Userid,Url,Title")] Blog blog)
{
/*
return View(await _context.Tag.ToListAsync());
*/
var blogging02Context = _context.Tag.Include(t => t.blog);
return View(await blogging02Context.ToListAsync());
// return View (await _context.Tag.ToListAsync());
}
// GET: Tags/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var tag = await _context.Tag
.Include(t => t.blog)
.SingleOrDefaultAsync(m => m.Id == id);
if (tag == null)
{
return NotFound();
}
return View(tag);
}
// GET: Tags/Create
public IActionResult Create()
{
ViewData["BlogId"] = new SelectList(_context.Blog, "BlogId", "Title");
return View();
}
// POST: Tags/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,DispOrderNbr,tagItem,BlogId")] Tag tag)
{
if (ModelState.IsValid)
{
_context.Add(tag);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["BlogId"] = new SelectList(_context.Blog, "BlogId", "Title", tag.BlogId);
return View(tag);
}
// GET: Tags/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var tag = await _context.Tag.SingleOrDefaultAsync(m => m.Id == id);
if (tag == null)
{
return NotFound();
}
ViewData["BlogId"] = new SelectList(_context.Blog, "BlogId", "Title", tag.BlogId);
return View(tag);
}
// POST: Tags/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,DispOrderNbr,tagItem,BlogId")] Tag tag)
{
if (id != tag.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(tag);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TagExists(tag.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["BlogId"] = new SelectList(_context.Blog, "BlogId", "Title", tag.BlogId);
return View(tag);
}
// GET: Tags/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var tag = await _context.Tag
.Include(t => t.blog)
.SingleOrDefaultAsync(m => m.Id == id);
if (tag == null)
{
return NotFound();
}
return View(tag);
}
// POST: Tags/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int? id)
{
var tag = await _context.Tag.SingleOrDefaultAsync(m => m.Id == id);
_context.Tag.Remove(tag);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool TagExists(int id)
{
return _context.Tag.Any(e => e.Id == id);
}
}
}
君康利和Gimly,谢谢你的回复。
我已经尝试过 Gimly 的想法。
public async Task<IActionResult> Index()
{
return View(await _context.Blog.Include(b => b.Tags).ToListAsync());
}
然后 Visual Studio 告诉我“'Blog' 不包括 'Tags' 定义”错误。 所以我把标签改成了标签,我的 Visual Studio 说没问题。
public async Task<IActionResult> Index()
{
return View(await _context.Blog.Include(b => b.Tag).ToListAsync());
}
我在调试模式下运行我的代码,Web 应用程序返回以下错误。
处理请求时发生未处理的异常。
InvalidOperationException:传递到 ViewDataDictionary 的模型项的类型为“System.Collections.Generic.List1[urlapp12.Models.Blog]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable1[urlapp12.Models.UrlTag]”。
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(对象值)
非常感谢。
我将代码“/Views/Blogs/Index.cshml”改成如下,我可以成功执行。
@model IEnumerable<urlapp12.Models.Blog>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Userid)
</th>
<th>
@Html.DisplayNameFor(model => model.Url)
</th>
<th>
@Html.DisplayNameFor(model => model.LastUpdatedAt_UtcDt)
</th>
<th>
@Html.DisplayNameFor(model => model.LastUpdatedAt_LocalDt)
</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Userid)
</td>
<td>
<a href="@Html.DisplayFor(modelItem => item.Url)">@Html.DisplayFor(modelItem => item.Title)</a>
</td>
<td>
@Html.DisplayFor(modelItem => item.LastUpdatedAt_UtcDt)
</td>
<td>
@Html.DisplayFor(modelItem => item.LastUpdatedAt_LocalDt)
</td>
<td>
@foreach (var childItem in item.Tag)
{
@Html.DisplayFor(itemItem => childItem.tagItem)
}
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.BlogId">Edit</a> |
<a asp-action="Details" asp-route-id="@item.BlogId">Details</a> |
<a asp-action="Delete" asp-route-id="@item.BlogId">Delete</a>
</td>
</tr>
}
</tbody>
</table>
【问题讨论】:
-
根据异常,您的控制器操作方法似乎有问题。可以分享一下你的控制器方法的相关代码吗?
-
我在问题中添加了 BlogsController.cs 和 TagsController.cs。
-
您在
BlogsController中的Index()正在返回View()并带有Blog的集合,但在您的Blog/Index.cshtml视图中,指定的@model是IEnumerable<urlapp12.Models.UrlTag>。这就是您遇到异常的原因。
标签: c# entity-framework model asp.net-core-mvc parent-child