Creation of a rich content type...?

Topics: Customizing Orchard, General
Feb 17, 2014 at 10:55 AM
Hi all,

After several wasted hours of trying to get an image carousel module to work (which I have put down to a versioning issue), I finally gave up and resorted to Steve Taylor's approach, using Projections.

I have got this to work, but I'm now struggling to manage the resultant layout. My aim is to produce something like this, and eventually add it as a widget onto the page:


...with both the image and associated text generated using a custom content type in Orchard.

Firstly: What is the best way to go about this sort of requirement?

And secondly: Is it possible (...and if so, how?!) to have the above rendered by a razor view within my theme, allowing me to style it up accordingly, and to position the text and image(s) as per the image above?

Thanks in advance

Feb 17, 2014 at 11:23 AM
The projection/projector widget is going to render a shape, according to the selected layout. The carrousel will need some markup surrounding the list of carrousel items, and content items should be rendered as carrousel items.

I'm not sure if this is the best way, but for the requirement above, I would create the content type with fields, one text field and one media library picker field. I would create a query to filter content on the content type I created. I would have a shape layout for the query that will render the wrapping carrousel mark-up, ie. the surreounding ul (or div) tag(s) and it's classes. Then I would override the Content template for the content type, to render carrousel specific item mark-up, and place content item header, metadata, content and footer the way I want to render. Finally I would override field templates if necessary.

The fields can be added to the content type, or to content parts. If you want to group some fields together (ie. render one after another in the same div), you can create a content part and put the fields in it, and add the content part to the content type. You can change the place these fields and parts are rendered using file of the theme. You can for example put the image field to the footer using a <Place> tag that matches your content type, and render the Model.Footer in a div in the right half of the wrapping div.

Feb 17, 2014 at 9:38 PM
Hi kassobasi,

Thanks for responding so quickly.

I think I follow most of what you said, but what exactly do you mean by:

" I would have a shape layout for the query that will render the wrapping carrousel mark-up, ie. the surreounding ul (or div) tag(s) and it's classes."?

Following Steve Taylor's blog post (link above) about this, has resulted in me adding the following method to Providers\Layouts\LayoutShapes.cs:
        public void Carousel(dynamic Display, TextWriter Output, HtmlHelper Html, string Id, IEnumerable<dynamic> Items, IEnumerable<string> OuterClasses, IDictionary<string, string> OuterAttributes, IEnumerable<string> InnerClasses, IDictionary<string, string> InnerAttributes, IEnumerable<string> FirstItemClasses, IDictionary<string, string> FirstItemAttributes, IEnumerable<string> ItemClasses, string Interval, IDictionary<string, string> ItemAttributes)
            if (Items == null) return;

            var items = Items.ToList();
            var itemsCount = items.Count;

            if (itemsCount < 1) return;

            var outerDivTag = GetTagBuilder("div", Id, OuterClasses, OuterAttributes);
            var innerDivTag = GetTagBuilder("div", string.Empty, InnerClasses, InnerAttributes);
            var firstItemTag = GetTagBuilder("div", string.Empty, FirstItemClasses, FirstItemAttributes);
            var itemTag = GetTagBuilder("div", string.Empty, ItemClasses, ItemAttributes);
            var paginationTag = GetTagBuilder("ol", string.Empty, new List<string>() { "carousel-indicators" }, null);



            int i = 0;

            foreach (var item in items)
                if (i == 0)



            //Carousel Nav
            Output.Write("<a href=\"#{0}\" class=\"carousel-control left\" data-slide=\"prev\">&lsaquo;</a>", Id);
            Output.Write("<a href=\"#{0}\" class=\"carousel-control right\" data-slide=\"next\">&rsaquo;</a>", Id);


            Output.Write("<script>$(function () {$('#" + Id + "').carousel({" + (!string.IsNullOrEmpty(Interval) ? "interval: " + Interval : null) + "});}); </script>");
...but how can I specify a razor view for the rendering instead? I guess the heavy lifting is actually done on this line:
...but this just dumps out the entire custom content type (with associated parts) - how can I intercept this and change the formatting of it (ideally in a razor view so I don't have the hassle of pushing everything into the TextWriter!)?

And finally, how can I "override the Content template for the content type"? I don't understand where the logic is that looks up a template (view) for a custom content type. Is this derived from a naming convention...?
Feb 18, 2014 at 7:03 AM
OK, I didn't look at the link in your first post. This article is a bit old. Now there are new types of out-of-the-box projection layouts: Shape layout and Raw layout can be used to easily modify how the list itself is rendered.

The way I posted before requires no chance to the core modules. Follow Steve Taylor's post until the changes to the core, that is, create the content type and create the query for listing those content types. Instead of carrousel layout, select Shape layout, and give a name to the shape, say "MyCarrousel". You can have now a "MyCarrousel.cshtml" in your theme's Views folder that renders outer div and inner div, and navigation in this shape.

To render items of the carrousel, which are content items returned by the query, you will need to do this in MyCarrousel.cshtml:

var buildShapes = Model.BuildShapes;

@foreach(var shape in buildShapes()) {

Finally, yes, it's based on a naming convention. For a content type named CarrouselItem, the Content alternate template would be named Content-CarrosuelItem.cshtml. Check out

Feb 18, 2014 at 10:37 PM
Hi again,

Thanks a lot! This is now heading towards something that looks almost manageable...!

As a side question, can this same scenario be achieved using Lists of custom content types (rather than Projections and queries)?
Feb 19, 2014 at 7:08 AM
Edited Feb 19, 2014 at 7:30 AM
I don't know much about Orchard lists. What I know is they are rewritten (old Lists were deprecated) and new Lists is planned to be released in version 1.8. In Orchard roadmap doc it says the work is finished. That means you can checkout 1.x branch to find out what they can do.
Feb 19, 2014 at 1:13 PM
I've now added a "MyCarousel" view to my theme and can see that it's rendering it. However, is there an alternative method of outputting each content type/part, other than calling Display()?...What if I wanted to display, say, an anchor tag using the text from content type A, linking to an image file that is part of content type B?

By the way - thanks for the heads-up re 1.8....I'll look into it.
Feb 19, 2014 at 1:31 PM
You can set the output of Display to some variable in template code, and use it as you want.

Feb 19, 2014 at 8:46 PM

Thanks again. Hopefully someone else will benefit from this - I know I'm not alone...!
Feb 19, 2014 at 10:36 PM
Sorry - I've ran into another issue...

I've realised that in order for me to be able to manipulate the template that is responsible for producing the layout in the image above, I will need to interrogate the results of the Display() method call, and assign each child content (fields of the Carousel content type) to separate variables. Doing so will finally allow me to have complete control over the rendering of the data.

After a quick Google, I realised that people were achieving this using the ShapeHelper class, like so:
@Display(Util.ShapeHelper.Find((Orchard.DisplayManagement.Shapes.Shape)Model, "Parts_FieldName1"))
...but when I attempt this, I get a yellow screen of death, complaining that it can't find ShapeHelper. I had a quick look through the 1.7 source and it doesn't seem to be defined...!

I can't simply recreate Bertrand's suggested ShapeHelper class (here), because it's reliant upon ClaySharp, which I understand has now been deprecated in 1.7.

Any suggestions?
Feb 20, 2014 at 6:37 AM
You can try using file along with the Content template override, so that you render fields in desired content zones, Header, Footer, Metadata or Content. That should be enough to get the carrousel layout you posted.

Feb 20, 2014 at 7:29 AM
Is there another method, as I don't believe that will give me enough flexibility.

For example, how could I take the text value from Field1, and create a hyperlink using Field1's text and setting the href attribute to the value of Field2?
Feb 20, 2014 at 10:53 AM
Best practice is to have no dependency between fields. They should be independent, because the content definition is changed and a field can be removed.

That aside, what you can do is, in Content-CarrouselItem.cshtml, get the field values without rendering them. You can get field objects with a syntax like
var myField = Model.ContentItem.CarrouselItem.<Field Name Here>;

, where Model is dynamic content shape. Then you can use field data as you like. Check to see public properties of different fields. You would probably need to suppress field rendering using, placing shapes to "-" zone.

Feb 21, 2014 at 7:46 AM
I've created the Content-xxxxx.cshtml view, and added the following:
    var myField1 = Model.ContentItem.CarouselContentType.TextField1;
    var myField2 = Model.ContentItem.CarouselContentType.TextField2;
    var myImageField = Model.ContentItem.CarouselContentType.ImageField;

    <a href="@myField1.Value">@myField2.Value</a>
    <img src="@myImageField.MediaParts[0].MediaUrl" width="300px" height="200px" />
Whilst debugging, I can see that the above code is hit, and the values are correctly populated!...However, the html at the bottom is not being output at all. Does this need to be passed through to a Display method?
Feb 21, 2014 at 8:59 AM
No. It's got to be somewhere in the generated HTML unless commented out on server. Or maybe some exception is thrown and swallowed. Can you try getting the values myField.Value etc in the code bloack into vars and see if they cause any exceptions? You can also try activating break on any CLR exception when debugging in case the exception is caught and ignored.

Feb 21, 2014 at 10:09 PM
Nope - it's definitely not in the source, and it's definitely not throwing any exceptions. Stepping through the code in this content part, I can see that each variable is being assigned to correctly.

I've tried changing the display type of the shape layout to "Summary" and "Detail", and changed between "Content" and "Property" display modes, but nothing seems to work.

Should content part HTML be presented in a specific way, or within a div with a certain id, or something equally ridiculous?
Feb 21, 2014 at 11:40 PM

No special html or div id or such. If the razor code block is hit in the template, i can't think of anything but a display call. Is it possible the result of display call is stored in a var in some template and not written to the response?

Feb 22, 2014 at 8:53 AM
I've now removed ALL content retrieval logic and trying to output a simple <p> tag in the content part, but even that isn't being displayed (even though, again, the code is definitely being hit!). Is there something that needs to be done specifically in the parent view (CarouselShape.cshtml) to cause the rendering of any child parts?

Alternatively, could be taking over and preventing anything from being displayed?

Thanks for your continued patience in helping out a newbie!
Feb 22, 2014 at 9:09 AM
Isn't it a problem with your ?
Feb 22, 2014 at 10:13 AM

In case of shape layout, you need to get Model.BuildShapes into a var and call it as a method, which will return an enumerable of shapes. These shapes are Content shapes if projection display mode is Content. Then you need to @Display these shapes. Since the code block in Content-CarrouselType.cshtml is hit, I figure nothing is missing there. Maybe the @ sign before Display?

With, you can prevent rendering of shapes created by drivers, which are shapes of content parts and field. This is not the case here, since you take over all rendering in Content alternate.

What happens when you rename Content-CarrouselType.cshtml to something else? I would expect the OOTB Content.cshtml template renders the item, not formatted as you like, but that would eliminate the possibility of a problem with shape layout template.

Feb 22, 2014 at 12:19 PM
I've done it!

You were right - I was simply missing the @ sign from the Display() method call! Everything now renders exactly as I wanted.

Thanks very much for all the help.
Feb 22, 2014 at 2:52 PM
Good to know! I was running out of bullets.

You are welcome. Good luck!