How do pass value of a list using ViewBag in a partial view?

156 Views Asked by At

I have a view showing all posts in the database. And I need to create a partial view that contains the top 5 highest viewed posts.

Here is my PostController controller:

public class PostController : Controller
    {
        private readonly IUnitOfWork uow;

        public PostController(IUnitOfWork uow)
        {
            this.uow = uow;
        }

        public IActionResult Index()
        {
            var result = uow._post.GetAll().ToList();
            return View(result);
        }

        public IActionResult GetMostViewedPost()
        {
            var result = uow._post.GetMostViewedPost(5).ToList();
            ViewBag.MostViewedPost = result;
            return PartialView(result);
        }
    }

My Partial view:

<h3>Most Viewed Posts</h3>
@foreach (var post in ViewBag)
{
    <!-- Post preview-->
    <div class="post-preview">
        <h4 class="post-title">@post.Title</h4>
        <h5 class="post-subtitle" style="font-weight:200">@post.ShortDescription</h5>
        <p class="post-meta">
            Posted on @post.PostedOn
        </p>
    </div>
}

I'm using ViewBag to pass the data into Partial View. I tried some (dumb) ways, and they didn't work. Please guide me, and if anything is wrong with my code, help me to fix that.

2

There are 2 best solutions below

0
iman safari On

Try to change your code as follows: Create a class for the result:

public class Result 
{
    public List<Post> Posts{get;set;}
    public List<Post> MostViewedPost {get;set;}
}

Change your action method :

  public IActionResult Index()
    {
        var result=new Result();
         
        result.Posts = uow._post.GetAll().ToList();
        result.MostViewedPost=uow._post.GetMostViewedPost(5).ToList();
        return View(result);
    }

In your index.cshtml file add following lines(replace ... by your code):

@model Result
...
 @{await Html.RenderPartialAsync("Your PartialView name",Result.MostViewedResult)}
...

You don't need GetMostViewedPost action method anymore.

And change partial view as follows:

@model List<Post>
<h3>Most Viewed Posts</h3>
@foreach (var post in Model)
{<!-- Post preview--><div class="post-preview">
    <h4 class="post-title">@post.Title</h4>
    <h5 class="post-subtitle" style="font-weight:200">@post.ShortDescription</h5>
    <p class="post-meta">
        Posted on @post.PostedOn
    </p>
</div>
}
0
Vadim Martynov On

You assign the value of the 5 most popular posts to the ViewBag.MostViewedPost property, but in your View you are not reading from theViewBag.MostViewedPost property, but from the whole ViewBag. The correct code would look like this:

<h3>Most Viewed Posts</h3>
@foreach (var post in ViewBag.MostViewedPost)
{
    <!-- Post preview-->
    <div class="post-preview">
        <h4 class="post-title">@post.Title</h4>
        <h5 class="post-subtitle" style="font-weight:200">@post.ShortDescription</h5>
        <p class="post-meta">
            Posted on @post.PostedOn
        </p>
    </div>
}

Also you should ensure that you are rendering a partial view in main view with next code

@Html.Partial("GetMostViewedPost")

Note that it's a quick solution and it's better to use strongly typed model in your views including partial views.

The @model directive specifies the type of the model passed to a view or page. Razor exposes a Model property for accessing the model passed to the view.

Just update your GetMostViewedPost method:

public IActionResult GetMostViewedPost()
{
    var result = uow._post.GetMostViewedPost(5).ToList();
    return PartialView(result);
}

And then use @model syntax to declare a model type:

@model List<Post> 

<h3>Most Viewed Posts</h3>
@foreach (var post in Model)
{
    <!-- Post preview-->
    <div class="post-preview">
        <h4 class="post-title">@post.Title</h4>
        <h5 class="post-subtitle" style="font-weight:200">@post.ShortDescription</h5>
        <p class="post-meta">
            Posted on @post.PostedOn
        </p>
    </div>
}