Orchard shapes are the basic building block of the whole rendered UI. They are ordinary, although dynamically discovered and created by Orchard framework, Razor (.cshtml) view files. One of the coolest (and also the one that generates most of the beginners’ problems) thing about Orchard is it’s flexible nature by extensive use of C# 4.0 dynamic objects.
Suppose you have the following line of code:
@Display(New.MyShape(Text: “someText”, SomeProperty: someObject))
You may think at first: “What the hell is that?”. After that, I suppose, many of you would try ReSharper or some other tool to find out what’s going on – where is Display method declared, what is the New property and, at last, what is that MyShape thing doing there. Bump! No results How can it be that MyShape(…) method is nowhere declared?
What would you say if I told you that this line of code renders the /Views/MyShape.cshtml Razor view file with dynamic model containing two properties: Text and SomeProperty? “No way! This is not the .NET way of doing things.”.
But it is in fact MyShape(…) is a dynamically created method, which is responsible for rendering MyShape.cshtml file. The named parameters you provide are combined into one dynamic object as properties and passed as a view model into the rendered shape. So inside the MyShape.cshtml file you can make use of Model.Text and Model.SomeProperty properties. Display and New are built-in shape methods responsible for rendering markup (Display) and creation of shapes (New).
And getting to the point – the way Orchard shapes work, resembling ordinary methods with ordinary parameters but with Razor code inside, makes them a perfect tool to use (and reuse) as helpers.
They are even better than ordinary helpers because:
- You don’t have to render HTML from C# code (which looks terrible – long and unreadable code) – just use Razor syntax
- You don’t have to remember to use certain namespaces (by @using … ) – Orchard makes sure you got your shapes always available
- It makes your code more understandable (and concise btw), as shape names are derived from shape .cshtml file names which makes those files easy to find (not always though, but usually it’s true)
- They don’t need to be overridden, because all parameters are named/optional – less code, less trouble (take a look into the default MVC HTML helpers – every one has lots of overrides…)
And now, the drawbacks…:
- Use of dynamic objects – depending on what you need this can be thought of as a nice feature or a drawback. The better part is that this is what really makes Orchard so flexible and cool . The worse - Forget about Intellisense on Model property inside .cshtml files. A workaround to this is to cast a specific Model property (you know type of – eg. you know that Model.Text is a string) to that type at the beginning of a .cshtml file and use the strongly typed version instead. Also – forget about Intellisense when calling Display and New methods.
A short summary. If you want to create a reusable helper shape:
- Create an appropriate .cshtml file in the /Views folder of your module (eg. /Views/MyHelper.cshtml)
- Place an appropriate reusable Razor (HTML + C#) code inside
- Use it in your part shapes/shape overrides/field shapes – anywhere you like by using @Display(New.MyHelper(params)), where params are the named parameters you use inside the /Views.MyHelper.cshtml file as Model.param
Hope you find it useful in your future Orchard modules!