一个视图中的父子模型(多个模型)(ASP.NET核心(C#)+ MVC +实体框架)

时间:2018-04-30 07:10:28

标签: c# entity-framework model asp.net-core-mvc parent-child

我正在尝试在一个视图中创建一个具有Parent-Child模型(多个模型)的Web应用程序(ASP.NET Core + MVC + Entity Framework)。

以下是输入(输入No.1)。 这是" Views / Blogs / index.cshtml"

Image of Views/Blogs/index.cshtml

以下也是输入(输入No.2)。 这是" Views / Tags / index.cshtml"

Image of Views/Tags/index.cshtml

以下是我期待的输出(输出No.1)。
Image of Views/Blogs/index.cshtml

我写了以下内容"观看/博客/ 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);
        }
    }
}
junkangli和Gimly,谢谢你的回复。

我尝试过Gimly的想法。

public async Task<IActionResult> Index()
{
    return View(await _context.Blog.Include(b => b.Tags).ToListAsync());
}

然后Visual Studio告诉我&#34;&#39; Blog&#39;不包括&#39;标签&#39;定义&#34;错误。 所以我将标签更改为标签,我的Visual Studio称它是O.K。

public async Task<IActionResult> Index()
{
    return View(await _context.Blog.Include(b => b.Tag).ToListAsync());
}

我运行调试模式的代码,Web应用程序返回以下错误。

处理请求时发生未处理的异常。 InvalidOperationException:传递给ViewDataDictionary的模型项的类型为&#39; 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]&#39;。 Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(对象值)

非常感谢。

我更改了代码&#34; /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>

1 个答案:

答案 0 :(得分:0)

首先,关于你得到的异常,错误信息是非常明确的,并且@junkangli在其评论中解释说,你没有将正确的对象返回给View。 View需要IEnumerable<UrlTag>,并且您发送IEnumerable<Blog>

现在,关于问题的核心,您需要在查询中加载标记列表以获取博客列表,因此,在控制器的Index操作中,您应该执行以下操作:

public async Task<IActionResult> Index()
{
    return View(await _context.Blog.Include(b => b.Tags).ToListAsync());
}

然后,在您的视图中,您应该能够访问您的代码并创建一个while循环来显示所有代码。