views:

1047

answers:

3

In ASP.Net MVC I would like to render a different partial view depending on the renderview query string parameter.

Therefore providing the facility for the user to choose to view products by thumbnail or by details.

I have access to the chosen parameter in the controller but I do not know how to or, if I should be passing this to the view along with the products list so the view can implement the logic for deciding which partial view to display?

public ActionResult Products(string id, int? renderview)
{
    var products = productRepository.GetProducts(id).ToList();
    return View("Products", products);
}



<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MLBWebRole.Models.Product>>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Products
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Products</h2>

<p>This is the Products page</p>

<p><a href="?renderview=0">thumbnails</a>&nbsp;<a href="?renderview=1">details</a></p>


 <% if (renderview == 1)
     {%>
    <% Html.RenderPartial("ProductsDetailList"); %>
<% }
else
 { %>
<% Html.RenderPartial("ProductsThumbnailList"); %> 
  <% } %>

</asp:Content>
+1  A: 

Your View Should be something like:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Models.MyModel>" %>

Then in MyModel

Expose Property:

public bool RenderDetailView {get;set;}

In your controller action:

public ActionResult Products(string id, int? renderview)
{
    var products = productRepository.GetProducts(id).ToList();
    return View("Products", new MyModel {RenderDetailView = renderview.HasValue});
}

Then in your view, make check like:

<% if (Model.RenderDetailView)

Ideally, all the properties or parameters or data which a View needs in order to present itself should be part of Model.

I hope it helps.

Nitin Midha
ALso ProductList will also be the part of MyModel.
Nitin Midha
Hi Nitin, I started to follow your answer and I have created the ViewModel utalising the method public ProductsViewModel(bool renderDetailView, List<Product> productsList){this.RenderDetailView = renderDetailView;this.ProductsList = productsList;} and pass it to the Products page with return View("Products", new ProductsViewModel(true, products)); but for some reason the if Model.RenderDetailView line is never hit - all the rest of the page is rendered but any code within <% %> are not being hit. Aso I can step through and see the ProductsViewModel being populated. Any suggestions?
Nicholas Murray
Can you please show your view and Controller code?
Nitin Midha
Thanks for your response! Meantime I deleted and recreated the view and also changed the view model code to be a nullable type to public bool? RenderDetailView { get; private set; } and now it works a treat! I like Paul's way as well but I think your way makes the most sense in this scenerio. What do you think?
Nicholas Murray
Well Ideally Your code should be like:You have a Page let us say product page.In that you have two partial views in the form of controls, driven by same Model and Controller. Then on Action use Partial Rendering of Either of the Control. By using Paul way you have to rewrite the functionality which is common to both the views, which i personally don't prefer.
Nitin Midha
Yes, I suppose it depends on your interpretation of what a partial view is for. Anyhow, I prefer your way.
Nicholas Murray
My approach turns the problem on it's head, you have 1 view and 2 partials. I would had 2 views and one partial (for the common stuff). I have no need for the renderview parameter and my view models are atomic and my views are single purpose. It's a matter of design, not saying you are wrong at all.
Paul
+3  A: 

An alternative approach would be to use Restful Urls to invoke the appropriate controller action and view.

This makes the urls reflect what you are seeing on the screen and makes the design more extensible; should you need to add other views of the data in the future (summary, latest, etc) you add the new view, no need for partials unless the main body of the view gets more complicated and has to be factored out to a partial view.

The URLs would look like:

~/product/1/detail

~/product/1/thumbnail

And correspond to ProductController methods:

public ActionResult Detail(String id)
{
    var products = productRepository.GetProducts(id).ToList();
    return View("Detail", products);
}

public ActionResult Thumbnail(string id)
{
    var products = productRepository.GetProducts(id).ToList();
    return View("Thumbnail", products);
}

You enable the routing with a route like:

{controller}/{id}/{action}
Paul
A: 

Paul's method is good, but if you decide you want to pass the int, you need to create a view model.

In your controller add this

public class ProductsFormViewModel
    {
        // Properties
        public Products Products { get; private set; }
        public int? Renderview { get; private set; }

        // Constructor
        public ProductsFormViewModel(Products p_products, int? p_renderView)
        {
            Products = p_products;
            Renderview = renderView;
        }
    }

Then pass this into the view

return View(new ProductsFormViewModel(products, renderview);

And then in the view

Inherits="System.Web.Mvc.ViewPage<YourNamespace.Controllers.ProductsFormViewModel>"
Wil