asp.netasp.net-coremodel-view-controller

Resolving InvalidOperationException when Passing ViewBag Content List to Partial View in ASP.NET MVC


When I call the partial view inside normal view, I'm getting this error; InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.String', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List`1[EntityLayer.Concrete.Content]'.

DefaultController.cs

using BusinessLayer.Concrete;
using DataAccesLayer.Concrete;
using DataAccesLayer.EntityFramework;
using Microsoft.AspNetCore.Mvc;
using EntityLayer.Concrete;
using Microsoft.AspNetCore.Authorization;

namespace MvcCamp.Controllers
{
    [AllowAnonymous]
    public class DefaultController : Controller
    {
        HeadingManager headingManager = new HeadingManager(new EfHeadingDal(new Context()));
        ContentManager contentManager = new ContentManager(new EfContentDal(new Context()));

        public IActionResult Headings()
        {
            var headingList = headingManager.GetList();
            ViewBag.ContentList = contentManager.GetList();
            return View(headingList);
        }

        public PartialViewResult Index(int id = 0)
        {
            var contentList = contentManager.GetListByHeadingId(id); // Fetches content filtered by heading ID
            return PartialView(contentList);
        }

    }
}

Headings.cshtml

@model List<EntityLayer.Concrete.Heading>
@using EntityLayer.Concrete

@{
    Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>Admin Dashboard</title>
    <!-- Font Awesome Icons -->
    <link rel="stylesheet" href="/AdminLTE-3.0.4/plugins/fontawesome-free/css/all.min.css">
    <!-- IonIcons -->
    <link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="/AdminLTE-3.0.4/dist/css/adminlte.min.css">
    <!-- Google Font: Source Sans Pro -->
    <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
</head>
<body class="hold-transition sidebar-mini">
    <div class="wrapper">
        <aside class="main-sidebar sidebar-dark-primary elevation-4">
            <div class="sidebar">
                <div class="user-panel mt-3 pb-3 mb-3 d-flex">
                    <div class="info">
                        <a href="#" class="d-block">MVC Yazar Paneli</a>
                    </div>
                </div>
                <div class="user-panel mt-3 pb-3 mb-3 d-flex">
                    <div class="image">
                        <img src="/AdminLTE-3.0.4/dist/img/user2-160x160.jpg" class="img-circle elevation-2" alt="User Image">
                    </div>
                    <div class="info">
                        <a href="#" class="d-block">Alexander Pierce</a>
                    </div>
                </div>
                <nav class="mt-2">
                    <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
                        @foreach (var item in Model)
                        {
                            <li class="nav-item">
                                <a href="javascript:void(0);" onclick="loadContent(@item.HeadingID)" class="nav-link">
                                    <p>@(item.HeadingName.Length > 25 ? item.HeadingName.Substring(0, 25) + "..." : item.HeadingName)</p>
                                </a>
                            </li>
                        }
                    </ul>
                </nav>
            </div>
        </aside>
        <div class="content-wrapper">
            <div class="content" id="dynamicContent">
                @Html.Partial("~/Views/Default/Index.cshtml", "Default")
            </div>
        </div>
    </div>
    <script src="/AdminLTE-3.0.4/plugins/jquery/jquery.min.js"></script>
    <script src="/AdminLTE-3.0.4/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
    <script src="/AdminLTE-3.0.4/dist/js/adminlte.js"></script>
    <script>
        function loadContent(headingId) {
            $.ajax({
                url: '@Url.Action("Index", "Default")',
                type: 'GET',
                data: { id: headingId },
                success: function (data) {
                    $('#dynamicContent').html(data);
                },
                error: function () {
                    alert('Error loading content.');
                }
            });
        }
    </script>
    <!-- Other scripts -->
</body>
</html>

Index.cshtml(Partial)

@model List<EntityLayer.Concrete.Content>

<!DOCTYPE html>
<html>
<body class="hold-transition sidebar-mini">
    <!-- Site wrapper -->
    <div class="wrapper">
        <section class="content">
            <div class="container-fluid">
                <!-- Timelime example  -->
                <div class="row">
                    <div class="col-md-12">
                        <!-- The time line -->
                        <div class="timeline">
                            <!-- timeline time label -->
                            @foreach (var item in Model)
                            {
                                if (item != null)
                                {
                                    <br />
                                    <div class="time-label">
                                        <span class="bg-success"> @item.ContentDate.ToString("dd-MMM-yyyy") - @item.Writer.WriterName @item.Writer.WriterSurName</span>
                                    </div>
                                    <!-- /.timeline-label -->
                                    <!-- timeline item -->
                                    <div>
                                        <i class="fas fa-comment bg-yellow"></i>
                                        <div class="timeline-item">
                                            <h3 class="timeline-header">
                                                <a href="#">
                                                  @item.Heading.HeadingName
                                                </a>
                                            </h3>
                                            <div class="timeline-body">
                                                @item.ContentValue
                                            </div>
                                        </div>
                                    </div>
                                }
                            }
                            <!-- END timeline item -->
                        </div>
                    </div>
                    <!-- /.col -->
                </div>
            </div>
            <!-- /.timeline -->
        </section>
        <!-- /.content -->
    </div>
    <!-- ./wrapper -->
</body>
</html>

I also tested different methods like Ajax Call, I tried to add ViewBag but it doesn't work as expected.


Solution

  • After testing, change

    @Html.Partial("~/Views/Default/Index.cshtml", "Default")
    

    to

    @Html.Partial("~/Views/Default/Index.cshtml", (List<Content>)ViewBag.ContentList)
    

    can fix the issue.

    Since I don't have css/js files like you, some there is no style in my test page.

    enter image description here