【问题标题】:How to pass IEnumerable model to _Layout.cshtml如何将 IEnumerable 模型传递给 _Layout.cshtml
【发布时间】:2020-10-26 05:47:09
【问题描述】:

我需要将模型传递给 _Layout 页面以进行动态内容编辑。

这是我的_布局

@model IEnumerable<Test.Models.Article>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
...

稍后在 _Layout 中我需要使用这个:

@Html.Raw(Model.Where(x => x.Id == 1).Single().Content) - this works fine
<a asp-controller="Articles" asp-action="Edit" asp-route-id="1">Edit</a> - error after clicking the edit button

这个概念在 Index、About 等所有页面上都可以正常工作,但在 _Layout.cshtml 上却不行。

我收到此错误:

InvalidOperationException:传递到 ViewDataDictionary 的模型项的类型为“Test.Models.Article”,但此 ViewDataDictionary 实例需要“System.Collections.Generic.IEnumerable`1[Test.Models.Article] 类型的模型项'。

我该怎么办?

编辑: 这是我的 HomeController:

    public class HomeController : Controller
{
    public ApplicationDbContext _context;

    public HomeController(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index()
    {
        return View(await _context.Article.ToListAsync());
    }

    public async Task<IActionResult> About()
    {
        return View(await _context.Article.ToListAsync());
    }
}

这是我的 ArticleController:

    public class ArticlesController : Controller
{
    public ApplicationDbContext _context;

    public ArticlesController(ApplicationDbContext context)
    {
        _context = context;
    }

    // GET: Articles
    public async Task<IActionResult> Index()
    {
        return View(await _context.Article.ToListAsync());
    }

    // GET: Articles/Edit/5
    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var article = await _context.Article.FindAsync(id);
        if (article == null)
        {
            return NotFound();
        }
        return View(article);
    }

    // POST: Articles/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,Content")] Article article)
    {
        if (id != article.Id)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            try
            {
                _context.Update(article);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ArticleExists(article.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction(nameof(Index));
        }
        return View(article);
    }

整个_Layout:

@model IEnumerable<Test.Models.Article>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - PermanentTetovani</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
        <link rel="stylesheet" href="~/css/default.css" />

        <link rel="stylesheet" href="~/lib/font-awesome/css/font-awesome.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />

        <link rel="stylesheet" href="~/lib/font-awesome/css/font-awesome.min.css" />
    </environment>
</head>
<body>
    <partial name="_CookieConsentPartial" />

    <!-- HEADER : begin -->
    <header id="header" class="m-animated">
        <div class="header-bg">
            <div class="header-inner">

                <!-- HEADER BRANDING : begin -->
                <div class="header-branding">
                    <a asp-controller="Home" asp-action="Index"><img src="../images/logo.png" alt="Permanentní tetování" data-hires="../images/logo.2x.png" width="291"></a>
                </div>
                <!-- HEADER BRANDING : end -->
                <!-- HEADER NAVIGATION : begin -->
                <div class="header-navigation">

                    <!-- HEADER MENU : begin -->
                    <nav class="header-menu">
                        <button class="header-menu-toggle" type="button"><i class="fa fa-bars"></i>MENU</button>
                        <ul>
                            <li class="@((ViewBag.PageName == "Index") ? "m-active" : "")">
                                <span><a asp-controller="Home" asp-action="Index">Úvodní stránka</a></span>
                            </li>
                            <li class="@((ViewBag.PageName == "About") ? "m-active" : "")">
                                <span><a asp-controller="Home" asp-action="About">O nás</a></span>
                            </li>
                            <li class="@((ViewBag.PageName == "Gallery") ? "m-active" : "")">
                                <span><a asp-controller="Home" asp-action="Gallery">Galerie</a></span>
                            </li>
                            <li class="@((ViewBag.PageName == "Contact") ? "m-active" : "")">
                                <span><a asp-controller="Home" asp-action="Contact">Kontakt</a></span>
                            </li>
                        </ul>
                    </nav>
                    <!-- HEADER MENU : end -->
                </div>
                <!-- HEADER NAVIGATION : end -->
                <!-- HEADER PANEL : begin -->
                <div class="header-panel">

                    <button class="header-panel-toggle" type="button"><i class="fa"></i></button>

                    <!-- HEADER RESERVATION : begin -->
                    <div class="header-reservation">
                        <a asp-controller="Home" asp-action="Contact" class="c-button">Domluvit si schůzku</a>
                    </div>
                    <!-- HEADER RESERVATION : end -->
                    <!-- HEADER CONTACT : begin -->
                    <div class="header-contact">
                        <ul>

                            <!-- PHONE : begin -->
                            <li>
                                <div class="item-inner">
                                    <i class="ico fa fa-phone"></i>
                                    <strong>721 805 741</strong>
                                </div>
                            </li>
                            <!-- PHONE : end -->
                            <!-- EMAIL : begin -->
                            <li>
                                <div class="item-inner">
                                    <i class="ico fa fa-envelope-o"></i>
                                    777michaelahavlova<br>
                                    @@seznam.cz
                                </div>
                            </li>
                            <!-- EMAIL : end -->
                            <!-- ADDRESS : begin -->
                            <li>
                                <div class="item-inner">
                                    <i class="ico fa fa-map-marker"></i>
                                    <strong>PERMANENT TETOVÁNÍ</strong><br>
                                    Jihočeská univerzita, Vančurova 2904<br>
                                    Tábor 390 01
                                </div>
                            </li>
                            <!-- ADDRESS : end -->
                            <!-- HOURS : begin -->
                            <li>
                                <div class="item-inner">
                                    <i class="ico fa fa-clock-o"></i>
                                    <dl>
                                        <dt>Po. - Pá.:</dt>
                                        <dd>Dle dohody</dd>
                                        <dt>So.:</dt>
                                        <dd>Dle dohody</dd>
                                        <dt>Ne.:</dt>
                                        <dd>Zavřeno</dd>
                                    </dl>
                                </div>
                            </li>
                            <!-- HOURS : end -->

                        </ul>
                    </div>
                    <!-- HEADER CONTACT : end -->
                </div>
                <!-- HEADER PANEL : end -->

            </div>
        </div>
    </header>
    <!-- HEADER : end -->
    <!-- WRAPPER : begin -->
    <div id="wrapper">

        @RenderBody()

        <!-- BOTTOM PANEL : begin -->
        <div id="bottom-panel">
            <div class="bottom-panel-inner">
                <div class="container">
                    <div class="row">
                        <div class="col-md-6">

                            <!-- BOTTOM TEXT : begin -->
                            <div class="bottom-text various-content">
                                <h3>O našem studiu</h3>
                                <!--
                                <p><strong>Permanentní make-up</strong> provádím v Táboře v Jihočeské univerzitě, kde nabízím tyto služby: <strong>permanentní tetování obočí, rtů a očních linek</strong>.</p>
                                <p>Je potřeba se nejprve předem objednat!</p>
                                -->

                                @Html.Raw(Model.Where(x => x.Id == 1).Single().Content)
                                <a asp-controller="Articles" asp-action="Edit" asp-route-id="1">Edit</a>
                            </div>
                            <!-- BOTTOM TEXT : end -->

                        </div>
                        <div class="col-md-6">

                            <!-- BOTTOM SUBSCRIBE : begin -->
                            <div class="bottom-subscribe various-content">

                                <h3>Kontakt</h3>
                                <p>Využijte prosím náš kontaktní formulář.</p>
                                <a asp-controller="Home" asp-action="Contact" class="c-button">Kontaktujte nás</a>
                            </div>
                            <!-- BOTTOM SUBSCRIBE : end -->

                        </div>
                    </div>
                </div>
            </div>
        </div>
        <!-- BOTTOM PANEL : end -->
        <!-- FOOTER : begin -->
        <footer id="footer">
            <div class="container">

                <!-- FOOTER BOTTOM : begin -->
                <div class="footer-bottom">
                    <div class="row">
                        <div class="col-md-6 col-md-push-6">

                            <!-- FOOTER MENU : begin -->
                            <nav class="footer-menu">
                                <ul>
                                    <li><a asp-controller="Home" asp-action="Index">Úvodní stránka</a></li>
                                    <li><a asp-controller="Home" asp-action="About">O nás</a></li>
                                    <li><a asp-controller="Home" asp-action="Gallery">Galerie</a></li>
                                    <li><a asp-controller="Home" asp-action="Register">Administrace</a></li>
                                </ul>
                            </nav>
                            <!-- FOOTER MENU : end -->

                        </div>
                        <div class="col-md-6 col-md-pull-6">

                            <!-- FOOTER TEXT : begin -->
                            <div class="footer-text">
                                <p>
                                    ©
                                    <script type="text/javascript">
                                        var today = new Date()
                                        var year = today.getFullYear()
                                        document.write(year)
                                    </script>
                                    PermanentTetovani.cz | Vytvořil <a href="http://www.prognet.cz/">ProgNet.cz</a>
                                </p>
                            </div>
                            <!-- FOOTER TEXT : end -->

                        </div>
                    </div>
                </div>
                <!-- FOOTER BOTTOM : end -->

            </div>
        </footer>
        <!-- FOOTER : end -->

    </div>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
        </script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd">
        </script>
        <script src="~/js/site.min.js" asp-append-version="true"></script>
    </environment>

    @RenderSection("Scripts", required: false)
</body>
</html>

【问题讨论】:

  • 检查控制器中的方法。您可能通过了一篇文章而不是 IEnumerable of Articles
  • 其实我需要所有的文章,因为我有动态的网页内容编辑。这意味着每个段落都是一篇文章。因此,像索引这样的一页有例如 5 篇文章。根据 ID,我在页面上显示文章。我的家庭控制器:公共类 HomeController:控制器 { public ApplicationDbContext _context;公共 HomeController(ApplicationDbContext 上下文) { _context = context; } public async Task Index() { return View(await _context.Article.ToListAsync()); }
  • @LukášHavel 您能否编辑您的问题并包括HomeControllerArticlesController 以及布局的其余部分?
  • Articles 控制器的编辑操作提供的模型是什么?我认为问题在于从编辑操作到布局。你能提供编辑操作方法吗?
  • @Florin-Constantin Ciubotariu 请参阅上面的编辑

标签: asp.net-core


【解决方案1】:

@Lukáš,我找到了您异常的原因,并会尽力描述它。 从下面的过程来看,当重新加载edit view时,它将加载_layout.cshtml然后渲染Edit.cshtml。你定义了@model IEnumerable 但返回视图(文章)。

最简单的解决方案是什么?

打开Views/Articles/Edit.cshtml下面添加代码

@{
    Layout = null;
}

测试截图:

警告

我必须提醒你,即使Edit 有效,但其他人仍然有同样的问题。 _Layout.cshtml 已从 _ViewStart.cshtml 添加到每个 Views

指定的布局可以使用完整路径(例如,/Pages/Shared/_Layout.cshtml 或 /Views/Shared/_Layout.cshtml)或部分名称(例如:_Layout)。当提供部分名称时,Razor 视图引擎使用其标准发现过程搜索布局文件。首先搜索处理程序方法(或控制器)所在的文件夹,然后是 Shared 文件夹。此发现过程与用于发现部分视图的过程相同。

ASP.NET Core 中关于Layout 的详细信息。

【讨论】:

  • 您好,非常感谢。我已经明白了。但是又出现了另一个问题……如果我单击“编辑”按钮并显示“编辑视图”,我将看不到我的所见即所得编辑器。它在@section 脚本中。在显示编辑视图时我也看不到 _Layout。有什么解决办法吗?
  • 设置@{ Layout = null; } ,_Layout 不会加载到您的编辑视图中,它会解决 @model 冲突(您的问题),但您看不到 _Layout 和脚本。
  • 不推荐但简单的解决方案是将您需要的 _Layout 代码复制到您的编辑视图中。推荐但耗时的解决方案是我的第一个答案中提到的重新编码_Layout。
  • 谢谢,您的解决方案解决了我的问题。它只有一个缺点:我在编辑视图中看不到我的布局。就我而言,我终于做了一个解决方法:我改用View Components。这正是我所需要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-16
  • 1970-01-01
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多