ASP.NET MVC Tutorial

Using ASP.NET MVC Partial View Controller Action

knowventBanner

Developing a single page rendering shouldn’t require a single uber model. ASP.NET MVC lends itself to require one model per Render View instance. The content of your browser should be build to consist of a collection of views. Your Login/Logout/Profile view in the header, a side navigation with data driven badge counts and the body which many contain many different view contexts as well.

I first touched on this a couple of months ago with my article ASP.NET MVC, Bootstrap and Knockout.js with a ~twist~ if you are interested in checking is out.

Using ASP.NET MVC Partial Controller Action with Their Own Models.

Before we dive too far into this tutorial, this is not a how-to using @Html.RenderPartial("*.cshtml", Model) or @html.partial("*.cshtml", Model). The problem with using those helpers is that your partial’s model must be a member of the parent view’s model. This is handy for reusing templates for a single view (like a table view row) but not so helpful if you are using it to render across many different views with its own actions and models.

The Widget Scenario

Widgets are components that contain view renderings and data. Widgets may be used anywhere across an application regardless of it containing view context. How do you achieve this while maintaining a DRY standard? You have to create partial cshtml view with a registered controller action. This action will return an ActionResult using the PartialView(Model) function. This, in turn, can be implemented via the extension method @Html.Action("ActionName", "ControllerName").

The Widgets’s Partial cshtml

Below is the markup used to define the Widget. You will notice it is using Knockout.js bindings definitions. The pattern set forth can support both MVC Helper bindings or Knockout’s MVVM bindings. Let me detail what is being done here, starting with the view.

<div id="cntrWidgetUserStats">

    <h2>@ViewBag.Title<small><a class="glyphicon glyphicon-refresh pull-right" href="#" data-bind="click: refresh"></a></small></h2>

    <ul class="nav nav-pills nav-stacked">
        <li>
            <span class="badge pull-right" data-bind="text: VisitCount"></span>
            Total Visits
        </li>
        <li>
            <span class="badge pull-right" data-bind="text: ConsecutiveDaysVisited"></span>
            Consecutive Visits
        </li>
        <li>
            <span class="badge pull-right" data-bind="text: UserScore"></span>
            User Score
        </li>
    </ul>
</div>
@Html.RenderPartialKnockoutResourceWithScope("UserStats", "Widget", (string)Model.ToJson(), "cntrWidgetUserStats")

Our view is defined with the knock field binding to the text property as well as a refresh function bound to the ‘click’ event for the button at top. Also notice the cntrWidgetUserStats div element wrapping the view content. This is used to defined the Knockout applyBindings binding scope so we can use multiple binding instances on a single view.

The important part with the view’s MVVM/Knockout binding is the custom @Html.RenderPartialKnockoutResourceWithScope MVC extension method. This is the Glue between the markup, view model and the knockout implementation.

To touch briefly on the method seen above the @Html.RenderPartialKnockoutResourceWithScope does the following:

  • ViewModel Registration: Every view requiring MVVM implementation should have a Javascript View Model definition. It expects to file the js file using this pattern: /Scripts/app/Views/{Controller}/{Action}.ViewModel.js
  • Knockout Model & MVC Model Mapping: During initialization it will take MVC’s (string)Model.ToJson() model data and map it to a Knockout observable object. This
  • Knockout Initialization: Once the supporting view model class is registered it will be initialized and applyBindings will be called. The actuates the glue that is Knockout’s MVVM.

If you want to know more info on how to implement this functionality with @Html.RenderPartialKnockoutResourceWithScope feel free to check ou my other article on ASP.NET MVC Model to Knockout Viewmodel to see how Knockout resources are managed and MVC models are shared.


Render a View Action on the View

As noted above, we what the view to use its own controller/action and data model. To achieve this you will need to invoke the following Html Helper method:

@Html.Action("UserStats", "Widget")

Since this asp.net mvc partial view controller action will be only used in a partial view context you would need to ensure the controller returns a PartialView ActionResult. This, of course, will allow you to use a model specific to your defined partial view:

public ActionResult UserStats()
{
   return PartialView(new UserStatsModel()
   {
        UserScore = "+233",
        VisitCount = "6203",
        ConsecutiveDaysVisited = "12"
   });
}

Let me know what you think and if you have any questions.

Posted in .NET, Knockout, MVC and tagged , , , .