cheny
cheny

Reputation: 2725

asp.net mvc3: How to pass parameters from controller to a partial view which is designed to be called by RenderPage?

I have one partial view which will be called both by @RenderPage and a controller's action as well.

Here is the code to call it from another view with @RenderPage which passes parameters with the PageData[]:

        @foreach (var subTree in itemTree.SubTrees)
        {
            <li id ="@("LiOf" + subTree.Root.ID)" style = "margin-top: 0px">
                @RenderPage("~/Areas/MFC/Views/Items/_SubItemsTree.cshtml", subTree, itemTreeViewModel, false, Request.RawUrl, showOpenAsTreeRoot)
            </li>
        }

BTW, this partial view is a "treeNode" so it will be rendered many times by a single call.

And here is the code in the action of a controller which passes parameters with the Model and ViewBag, when a certain node need to be refreshed, this action will be called:

    var fatherTree = ItemTree.ItemTreeOf(item.FatherID);
    ViewBag.IsSubtreeRoot = true;
    ViewBag.ReturnUrl = returnUrl;
    ViewBag.ItemTreeViewModel = new ItemTreeViewModel(
        view, fatherTree, whats, types,
        showPopupOperationMenu: true, showMoveLeftRight: true, showMoveUpDown: true);
    ViewBag.ShowOpenAsTreeRoot = true;
    return View("~/Areas/MFC/Views/Items/_SubItemsTree.cshtml", fatherTree);

To work properly in the 2 cases, the view to be rendered is like this:

@model ItemTree
@using Martian.Areas.MFC.Models;
@{
    var itemTree = (PageData[0] as ItemTree) ?? Model;
    var itemTreeViewModel = PageData[1] ?? ViewBag.ItemTreeViewModel as ItemTreeViewModel;
    var isSubtreeRoot = (bool) (PageData[2] ?? ViewBag.IsSubtreeRoot);
    var returnUrl = PageData[3] ?? ViewBag.ReturnUrl as string;
    var showOpenAsTreeRoot = (bool)(PageData[4] ?? ViewBag.ShowOpenAsTreeRoot);

And yes, it works well yet looks awkward. As I have a pack of partial views needs to be transferred to be called by @RenderPage rather than @Html.RenderPartial, and they need to be returned by some action as well, this will be a problem. Is there any better way to do that? Thanks.


2013-01-19 A painful yet workable solution is here:

The train of the brain is that: if we can pass more than one parameters into the Controller.View, we can pass it to the cshtml as PageData[].

step 1. Modify the call from controller:

    public ActionResult AjaxRemoveUser(int departmentID, int teamID, string userName, int udcTypeValue)
    {
        var team = _repMFC.ReadItemAt<Department>(teamID);
        team.RemoveUser(udcTypeValue, userName);
        return MFCView("AssignMembers/_AjaxTeam", _repMFC.ReadItemAt<Department>(departmentID), team, true);
    }

step 2. Derive the controller from MFCController instead of controller and . MFCController is our class designed before for some other reason, and all of our controllers are derived from it.

In the MFCController, there is the body of MFCView() which looks like this:

    public ActionResult MFCView(string ajaxViewName, params object[] list)
    {
        var ajaxViewPath = ((BuildManagerCompiledView) (ViewEngines.Engines.FindPartialView(ControllerContext, ajaxViewName).View)).ViewPath;
        var viewModel = new MFCViewModel { AjaxViewPath = ajaxViewPath, PageData = list };
        return View("~/Views/Shared/_MFCView.cshtml", viewModel);
    }

step 3. MFCViewModel:

    public class MFCViewModel
    {
        public string AjaxViewPath;
        public object[] PageData;
    }

It's quite clear and straight forward.

step 4. ~/Views/Shared/_MFCView.cshtml

@model Martian.Areas.MFC.Models.MFCController.MFCViewModel
@{
    @RenderPage(Model.AjaxViewPath, Model.PageData)
}

step 5. In the view AssignMembers/_AjaxTeam.cshtml: As I described at the very beginning of the topic, it used to look like:

var department = (PageData[0]??ViewBag.Department) as Department;
var team = (PageData[1]??ViewBag.Team) as Department;
var enableEditMembers = (bool)(PageData[2]??ViewBag.EnableEditMembers);

And now it's actually:

var department = PageData[0] as Department;
var team = PageData[1] as Department;
var enableEditMembers = (bool) PageData[2]; 

Now, the PageData is created by the parameters we passed into MFCView().

Although the process looks painful, once u have finished the work, u can use the MFCView to pass as many parameters as u want, no ViewBag, no ViewData[], even no ViewModel! It looks like u are calling a normal method!

Upvotes: 1

Views: 1590

Answers (1)

slfan
slfan

Reputation: 9129

I think you could use @Html.RenderAction instead of RenderPage. Then you can design an action, pass parameters and choose your partial view.

There is a good blog here about this.

Upvotes: 0

Related Questions