Get content type for projected item

Topics: Customizing Orchard, Troubleshooting
Sep 20, 2013 at 2:42 AM
Where in the model is the content type of an item rendered from a projection?

I can see the content type for the projection itself, which displays "ProjectionPage"

In the query that the projection is rendering I was able to apply a filter using the content type, but I don't see that after it is rendered in the page using the shape tracer.

So if I am querying a content type of "Product" and rendering that in a projection, where can I get to the content type of the individual item displayed?
Sep 20, 2013 at 5:43 AM
Get to the list of filters for the projection, find that particular filter, and look for its settings? Or look at the first item in results and get its type?
Sep 20, 2013 at 6:39 AM
List of filters in the model?

Sent from my iPhone

Sep 20, 2013 at 7:02 AM
In the projection's query.
Sep 20, 2013 at 9:09 PM
But I need this information from the model...

Sent from my iPhone

Sep 21, 2013 at 12:10 AM
What model? I can't know what you're talking about if you don't say where you are writing this code.
Sep 21, 2013 at 1:06 AM
I want to know how to access the content type that is being projected in a view.

Sent from my iPhone

Sep 21, 2013 at 2:24 AM
That does not answer my question: from where? What is the name of the file where you want to write this code?
Sep 21, 2013 at 3:15 AM
I think we must be misunderstanding each other. Let see if I can flesh out the whole issue...

On my site, we support multiple languages.

On our main menu, we have an item called Products, which links to a page called Products.
On this "Products" page we have a side nav, where we are rendering multiple projections. These projects are serving as Product filters. One of the projections is called Data Providers.

This Data Providers projection renders a list of products (in the current culture) that have been flagged as a Data Provider product. (The flag is set on a custom content type called Product)

So for illustration purposes here is the menu heirarchy:
Products (Page Content Type linked to menu)
  • Data Providers (Projection)
    • List of Products (Custom Content Type, which supports multiple cultures)
We are nearly finished build this site, and the navigation coupled with the culture has become the bane of our existence for the moment.

We have been banging our heads trying to get the side nav (which represents level 2+ menu items) to play nice with cultures. We setup multiple menus as such:
Main menu - which is shown on the home page that contains the following (Products, About, News, etc...)
Products menu - which contains the projections (Data providers, Industry Partners, etc...)

So if you were click Products from the main menu the breadcrumbs would show: Home / Products
The side nav would show:
Data Providers
Industry Partners

If you clicked on the Data Providers projection you would see the listing of products that met the projection criteria, and the breadcrumb would now be:
Home / Products / Data Providers

If you clicked on one of the products the breadcrumb would now be: Home / Products / Product Name

All of this works in the "root" culture, but to get these items to show in the nav & breadcrumbs we were having to add to the Products menu the following in every culture:
Products Content page
Projections (Here's the rub, can't add projection more than once...)
Every product, we have 18 products x's 12 supported cultures

Also we hid the products from the side nav, in the view based on content type which we read from the model we applied a style to dom element and the use jQuery to hide it, so only want the projections to show, but the products had to be in the nav to work with breadcrumbs.

So our Products menu alone had 230 items, while a nightmare to administer it was quasi-working when we changed culture with exception of the projections. Because you can only put a projection once on a menu (and we understand why, it's basically culture agnostic), we couldn't get it show anywhere but the root culture.

We had the epiphany to just create queries / projections to render all the content of the products area (and all others area too).
This would allow us to write a query for the top level (current culture, type = page, title = Products).
Then just the existing projections for the next level (Data providers...)
And the a query for each Product (Current culture, type = Product, title = Product Name)

So we did all that and it was working like a champ... Our menu went down to about 20 items (just each individual item) making it manageable.

This approach leaves us with a couple new issues:
  1. The menus are no longer translating as we change culture (because they are simply showing the projection title, and not the content title)
  2. I can't hide the products from the side nav because I no longer see their content type when they render due to them being projections, thus I wondered where can I get the content type of the thing being projected.
Here is the code that I use to hide the items, perhaps this will help some as well...
    // odd formatting in this file is to cause more attractive results in the output.
    var items = Enumerable.Cast<dynamic>((System.Collections.IEnumerable)Model);
    if (!HasText(Model.Text))
        if ((bool)Model.Selected)

        if (items.Any())

        // HACK: Hide the Products and OForm Inquiry Page in the products-menu
        if (Model.Item.Content != null)
            if (
                (Model.Menu.MenuName == "products-menu" & (Model.Item.Content.ContentItem.ContentType == "Product" || Model.Item.Content.ContentItem.ContentType == "OForm"))
                || (Model.Item.Content.ContentItem.ContentType == "OForm" & Model.Menu.MenuName == "news-menu")

@* morphing the shape to keep Model untouched*@
        Model.Metadata.Type = "MenuItemLink";

@* render the menu item only if it has some content *@
        var renderedMenuItemLink = Display(Model);
        if (HasText(renderedMenuItemLink))
            var tag = Tag(Model, "li");

            if (items.Any())
All in all, I just want a way to show culture aware items on the menu, where we have projections involved.

Sorry for being so long winded, but I hope that better explains the issue I am having.
Sep 21, 2013 at 4:44 AM
For 1., did you try to add the localizable part to the projection content type?

Still not sure what you mean in 2. What do you mean when you say that the products are projections? I would understand if you said they were rendered by a projection. What kind of layout are you using in this projection?
Sep 21, 2013 at 5:22 AM
I think making the projection itself localizable defeats the point of having current culture in the query. It seemed like that was the power and beauty of the projection.
I could create one projection which has a clean permalink and it would just render the culture specific content.
By giving the projection the "ability" to be translated, it would be creating culture specific projections

If the localization only applied to the title and I could use the same permalink everywhere that would be great because then as the culture changed so would the title, but the link could stay the same...

As for 2.
I do mean that I products render by a projection.
As for the layout, it is simply:

Display mode - Content
Display Type - Detail
Shape Type - GenericPage

The code of the "GenericPage" is:
    var buildShapes = Model.BuildShapes;

@foreach (dynamic shape in buildShapes())
Sep 21, 2013 at 5:38 AM
It also looks like you can still only have the projection in the menu once. Only the root version can be on the menu.
Sep 21, 2013 at 7:06 AM
I still don't understand. What did you try and how did it not work?
Sep 24, 2013 at 1:14 AM
Let me try to simplify my issue...
What is the recommended way to create navigation with a multilingual site when there are projections involved that include current culture in the filter, so that all items display in the translated text?

Stealing from my comment above:
Menu example:
Products (Page Content Type linked to menu)(I have also tried a projection, with a query of pages for current culture)
Data Providers (Projection)
List of Products (Custom Content Type, which supports multiple cultures)

I have added localization to the projections so they can now be translated.
Sep 24, 2013 at 1:43 AM
There is no recommended way. It depend how your site is localized. There are many ways to skin that cat. Some people have all their contents translated to all cultures, some don't, everybody has different fallback rules, some prefer to detect culture from the browser settings, some prefer to present this choice the first time the visitor sees the site, etc. Orchard is not prescribing one specific scenario.
Typically, you implement an ICultureSelector that switches the culture based on the specific set of criteria that you chose. Then all localizable contents will just display in the right culture. For navigation, some people choose to have separate menus for each culture (typically because they don't have all the same contents in all cultures) that they turn on and off using a culture layer, or they make sure all pieces of the menu can be localized. I don't know which scenario you're trying to implement.
Sep 24, 2013 at 2:03 AM
We use the CulturePicker to change languages.

I have tried going down the culture specific layer using culture("de-de") for example, but that doesn't seem to working as expected.

The items in the second level of my nav are what I'm trying to display on my side nav.
I have a menu widget on my culture layer, and have it set to start set at 1 and the levels to display set at 0.

I multiple languages represented in my menu, and when I choose German from the dropdown, I still get the English content...
Sep 24, 2013 at 2:23 AM
That may be a bug.
Sep 24, 2013 at 2:59 AM
I may have spoke to soon...
I think Culture rule is working.

When creating culture layers would you create a layer per culture per top nav or one culture layer and move all relevant content to that one layer?

I have started down the one layer per culture per top nav, and want to be sure I'm on the best path...
Sep 24, 2013 at 4:04 AM
Not following what you mean by "per top nav", but you need one layer per culture.
Sep 24, 2013 at 4:41 AM
Edited Sep 24, 2013 at 5:00 AM
Simply mean the top level of the navigation hierarchy.

My nav looks akin to this:
Products                       About                  News              Resources
     Data Providers              My Company               Media              Glossary
     Industry Partners           Meet the Team            Bios               FAQ
So the top nav is Products, About, etc...

I have a 12 cultures for every menu sections, so can I just create one layer per culture or one layer per culture per menu section?

I have been doing the latter so far tonight, and it seems to be working but if that isn't the way it should be done then I will change it.

Just looking for best practice. I wouldn't have thought that the navigation setup of my site would end up being my biggest stumbling block...
Sep 24, 2013 at 5:01 AM
Here's an example of the layer rule I'm applying:
url("~/news*") and culture("fr-fr")
then I would have one like
url("~/resources*") and culture("fr-fr")
Sep 24, 2013 at 5:36 AM
Yup, as I was saying, there is so much diversity in the way people implement localization that if it works for your site, well, go for it. I would probably try to find a way to minimize the number of layers, but that looks ok.