Alternate Part Has a Different Model

Topics: Customizing Orchard, Writing themes
Mar 28, 2012 at 12:51 AM

I have a content part called coverflow that I wanted to augment the view of on just the home page. I tried the "Url Alternates" module to no avail. Since the part is (in the Parts folder) Coverflow.cshtml, I named my alternate Coverflow-url-homepage.cshtml per the documentation, but nothing happens.

I can get an alternate to render on that page using placement.info. I renamed my alternate part Coverflow.Homepage.cshtml, and added this:

<Match Path="/">
   <Place Parts_Title="-" />
   <Place Parts_Coverflow="Content:1;Alternate=Parts_Coverflow_Homepage" />
</Match>

Orchard now renders my alternate instead of the template provided by the module. The only problem is that I can't use the model anymore. If I copy the exact same template the module usually renders, now I get an error:

The model item passed into the dictionary is of type 'IShapeProxyf5ec0bccdc1a414eabe523e4808d82c5', but this dictionary requires a model item of type 'PlanetTelex.Coverflow.ViewModels.CoverflowViewModel'.

Why does the alternate use a different model? I've attempted exploring this IShapeProxy model, but can't figure out how to access the coverflow model. Per the post at http://orchard.codeplex.com/discussions/233617 I've tried using Model.ContentItem.As<YouPart>().YouPartProperty but that extension method cannot be found, even with the using line included.

I can work around this issue, but using the alternates would be the elegant solution- any ideas on how to make them work with the model of the original part?

Coordinator
Mar 28, 2012 at 12:59 AM

Change your alternate template to remove the @Model declaration. Instead, work with the dynamic model. You can always cast from a @{} block.

Mar 28, 2012 at 1:18 AM

Thanks for the quick reply bertrandleroy! I'm happy to cast from a code block, I'm still confused about the object model.  Perhaps you can illustrate.  The original template is: 

@model PlanetTelex.Coverflow.ViewModels.CoverflowViewModel
@{ Script.Require("jQueryUI_Coverflow").AtHead(); }
@{ Style.Require("Coverflow").AtHead(); }

@if (Model.Covers.Count > 0)
{
    <div id="@Model.CoverflowId" class="coverflow">
        @foreach (var cover in Model.Covers)
        {
            <img src="@cover.ImagePath" alt="@cover.Title" data-title="@cover.Title" data-category="@cover.Category" />
        }
    </div>
    <script type="text/javascript">
        var $@Model.CoverflowId;
        $(function() {
            $@Model.CoverflowId = $("#@Model.CoverflowId").coverflow(@Model.SettingsJson);
        });
    </script>
}
What would the proper syntax be say, to access the Model.CoverflowId property?

Coordinator
Mar 28, 2012 at 1:22 AM

I can't check right now, but if you attach a debugger it should not be too hard to figure out by drilling into Model.

Mar 28, 2012 at 1:37 AM
Edited Mar 28, 2012 at 1:48 AM

You were correct, I did figure it out with the debugger. When using alternates, I've discovered 3 useful parts of the dynamic object:

  1. Model.Model - This was what I was looking for, the original view model.
  2. Model.ContentPart - The content part class that corresponds with the part.
  3. Model.ContentItem - Access to the entire content item, all its various parts and fields.

So to answer my own question from earlier, the original template can be configured exactly as an alternate by doing:

@{ Script.Require("jQueryUI_Coverflow").AtHead(); }
@{ Style.Require("Coverflow").AtHead(); }

@if (Model.Model.Covers.Count > 0)
{
    <div id="@Model.Model.CoverflowId" class="coverflow">
        @foreach (var cover in Model.Model.Covers)
        {
            <img src="@cover.ImagePath" alt="@cover.Title" data-title="@cover.Title" data-category="@cover.Category" />
        }
    </div>
    <script type="text/javascript">
        var $@Model.Model.CoverflowId;
        $(function() {
            $@Model.Model.CoverflowId = $("#@Model.Model.CoverflowId").coverflow(@Model.Model.SettingsJson);
        });
    </script>
}

Basically, add an additional "Model." to the front of everything. Now I can add my enhancements to this template that apply only to the homepage. Awesome!

Developer
Mar 28, 2012 at 8:17 AM

Also see this issue: http://orchard.codeplex.com/workitem/18195