1

I'm pretty new to MVC. I'm trying to create a page where a news story is pulled from a SQL Server database to populate the main area of the page, while I have a sidebar where all the headlines are listed. I've tried using a partial view for the sidebar.

Here's the code from the controller which populates the views:

        public ActionResult _ArticleList()
        {
            return View(db.Articles.OrderByDescending(a => a.id).ToList());
        }    

        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Articles articles = db.Articles.Find(id);
            if (articles == null)
            {
                return HttpNotFound();
            }
            return View(articles);

My main view - Details.cshtml

@model MyApplication.Models.Articles

    <div id="container">

        {
        <div id="main" class="col-md-9">

            <h2> @Html.DisplayFor(model => model.Headline)</h2>
            <p style="white-space:pre-line">
                @Html.DisplayFor(model => model.Content)
            </p>
        </div>
        <div id="rightnav" class="col-md-3">
            @Html.Partial("_ArticleList")

        </div>
    </div>

and my partial view - _ArticleList.cshtml

@model IEnumerable<MyApplication.Models.Articles>

@foreach (var item in Model)
{
    <a href="/Details/@item.id"> @Html.DisplayFor(modelItem => item.Headline)</a>
    <br>
}

I'm getting a conflict between @model MyApplication.Models.Articles in the main view and @model IEnumerable<MyApplication.Models.Articles> in the partial.

Can anyone suggest a way around this?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
John
  • 4,658
  • 2
  • 14
  • 23

2 Answers2

2
@Html.Partial("_ArticleList")
// and
@{Html.RenderPartial("_ArticleList");}

Means, load the CSHTML page and put it here with the current model (with Render versions more efficient). They are controllerless meaning there is no call to a controller.

If you need to load a HTML in a separate controller/method context, then you would use one of the following.

@Html.Action("_ArticleList")
// and
@{Html.RenderAction("_ArticleList");}

Again, using the Render Option is more performant.

The issue you may have is that both Action/Render will render out with any layouts you have, causing a really weird output (html tags within previous body tags possibly). To prevent this, instead of calling View() you can call PartialView() in your controller.

public ActionResult _ArticleList()
{
  return PartialView(db.Articles.OrderByDescending(a => a.id).ToList());
}  

I would also suggest that you lock down this method so that it can only be called by Action() or RenderAction() by using the ChildActionOnlyAttribute.

[ChildActionOnly]
public ActionResult _ArticleList()
{
  return PartialView(db.Articles.OrderByDescending(a => a.id).ToList());
}  
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • Many thanks. `Html.RenderAction` got me past the YSOD, but as you predicted it really messed up my Bootstrap layout. `return PartialView` solved that. – John Dec 27 '18 at 18:50
1

Replace @Html.Partial("_ArticleList") with @Html.Action("_ArticleList", "Articles"), that will run to your Articles controller and should use the partial view you created.

Casey
  • 309
  • 1
  • 6