3
votes

I have a strongly typed partial view that is rendered inside of _Layout.cshtml so that it is included in every page. Within that partial view I am attempting to render another partial view. I have created a view model (ShoutboxView) to use as the model for the parent view. When trying to render the child partial view (_ShoutList) within this, I am getting an error that the model I am passing in is of the incorrect type:

The model item passed into the dictionary is of type 'MvcForumTest.ViewModels.ShoutboxView', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcForumTest.Models.Shout]'.

Please see code below:

Model (Shout.cs):

namespace MvcForumTest.Models
{
    public class Shout
    {
        public int Id { get; set; }
        public string Author { get; set; }
        public string Message { get; set; }
        public DateTime EntryDate { get; set; }

        public Shout()
        {
            Id = 1;
            Author = "TestUser";
            EntryDate = DateTime.Now;
        }
    }
}

View Model (ShoutboxView.cs)

namespace MvcForumTest.ViewModels
{
    public class ShoutboxView
    {
        public Shout newShout { get; set; }
        public IEnumerable<Shout> Shouts { get; set; }
    }
}

Controller (ShoutController.cs):

namespace MvcForumTest.Controllers
{
    public class ShoutController : Controller
    {
        private ForumsContext db = new ForumsContext();

        public ActionResult Index()
        {
            ShoutboxView shoutboxView = new ShoutboxView
            {
                newShout = new Shout(),
                Shouts = (from s in db.Shouts
                          orderby s.EntryDate descending
                          select s).Take(20)
            };
            return PartialView(shoutboxView);
        }

        [HttpPost]
        public ActionResult AddShout(ShoutboxView shoutbox)
        {
            Shout shout = new Shout();
            shout.Message = shoutbox.newShout.Message;

            if (ModelState.IsValid)
            {
                db.Shouts.Add(shout);
                db.SaveChanges();
                return PartialView("Index", shoutbox);
            }

            //return PartialView("_ShoutList", db.Shouts);
            return PartialView("Index", shoutbox);
        }
    }
}

Index partial view (Index.cshtml). This is where I'm getting the error. On the "@Html.Partial("_ShoutList", Model.Shouts)" line:

@model MvcForumTest.ViewModels.ShoutboxView

@using (Ajax.BeginForm("AddShout", "Shout", new AjaxOptions { UpdateTargetId = "shoutboxWrapper", InsertionMode = InsertionMode.Replace}))
{
    @Html.EditorFor(model => model.newShout.Message)
    <input type="submit" value="Submit" />
}

<div id="shoutboxWrapper">
    @Html.Partial("_ShoutList", Model.Shouts)
</div>

Shout partial view (_Shoutlist.cshtml):

@model IEnumerable<MvcForumTest.Models.Shout>

@foreach (var item in Model)
{
    <div class="shout">
        <table>
            <tr>
                <td class="shoutDelete">
                @Html.ActionLink("Delete", "Delete", new { id=item.Id })
                </td>
                <td class="shoutAuthor">
                    @Html.DisplayFor(model => item.Author)
                </td>
                <td class="shoutDate">
                    @Html.DisplayFor(model => item.EntryDate)
                </td>
            </tr>
            <tr>
                <td class="shoutMessage">
                    @Html.DisplayFor(model => item.Message)
                </td>
            </tr>
        </table>
    </div>
}

How can I fix this? Should I be calling something other than @Html.Partial to render the child partial view? Or is there another way I should be passing in the child model?

Edit:

_Layout.cshtml:

<div id="body">
     @RenderSection("featured", required: false)
     <section class="content-wrapper main-content clear-fix">
          @Html.Action("Index", "Shout")
          @RenderBody()
     </section>
</div>
2

2 Answers

1
votes

I have re-created your project with the following change in ShoutController:

var shouts = (from s in db.Shouts
                  orderby s.EntryDate descending
                  select s)
                  .Take(20)
                  .ToList();

shouts.Add(new Shout{Author = "T", EntryDate = DateTime.Now, Id = 1, Message = "some message"});
shouts.Add(new Shout { Author = "T2", EntryDate = DateTime.Now, Id = 2, Message = "some message2" });

var shoutboxView = new ShoutboxView
{
    newShout = new Shout(),
    Shouts = shouts
};

return PartialView(shoutboxView);

and it loads up fine when visiting ~/Shout/Index. You are saying that inside _Layout.cshtml, there is a strongly typed partial view. Is Index that partial view? If that's the case, what is the full view which uses _Layout.cshtml and what is the action method for that one? That would be the code to look at.

0
votes

I think you should select Shouts AsEnumerable().

            return PartialView("_ShoutList", db.Shouts.AsEnumerable());