Best Practices for Migrating a Legacy-Based CMS to Drupal
Orchard Dynamic Class Extensions
1. Orchard Dynamic Class Extensions
(A Code Club Presentation)
May 14, 2012
Presenters
Mark Dolar
Nesim Sisa
Based on Article: Orchard Extensibility by Bertrand Le Roy
http://msdn.microsoft.com/en-us/magazine/hh708754.aspx
2. Orchard Dynamic Class Extensions
Key Questions -
Why does Orchard have virtual methods?
What does it mean to dynamically extend a class at
runtime?
Why dynamically extend a class at runtime?
How do I dynamically extend a class at runtime?
3. Orchard Dynamic Class Extensions
A Simple T/F Quiz about Orchard:
Content Items are the central content entity in Orchard and
T F are entities users consider an end- product (like Blog
Postings or a product page).
In Orchard, Content Types are classes of Content
T F Items.
In Orchard, Content Items are not instances of classes
T F such as BlogPost, Product or Widget.
In Orchard, Content Items are composed of Content Parts
where any two Content Items with common sets of
T F Content Parts are considered of the same Content Type
class.
4. Orchard Dynamic Class Extensions
A Simple T/F Quiz about Orchard:
T F Content Items in Orchard correspond to a URL.
MPEG-2 Video Stream Closed Captioning Data is a
T F Content Part in Orchard.
New Content Parts can by added to Orchard
T F without programming (ie. Visual Studio)
Development.
T F In Orchard, Content Items are instances of Content Types.
5. Orchard Dynamic Class Extensions
A Simple T/F Quiz about .NET:
T F C# is a statically typed language as opposed to
a dynamically typed language.
Static typing in C# means we can only describe
T F the fields, properties and methods inherent in all
dynamic objects, not the objects themselves.
6. Orchard Dynamic Class Extensions
What important things do we know about Orchard's
dynamic content types?
This is actually exactly how the blog post content type is defined
1.ContentDefinitionManager.AlterTypeDefinition
("BlogPost",
2. cfg => cfg
3. .WithPart("BlogPostPart")
4. .WithPart("CommonPart", p => p
5. .WithSetting
("CommonTypePartSettings.ShowCreatedUtcEditor",
"true"))
6. .WithPart("PublishLaterPart")
7. .WithPart("RoutePart")
8. .WithPart("BodyPart")
9. ); F
7. Orchard Dynamic Class Extensions
Extending the BlogPost content type dynamically
Two Approaches:
1. Adding an existing Content Part via a Yummy Recipe
-Comments
-Tags
2. Building a new Content Part via a Module
-Brand X GPS
-Metatag addition to page head example
-Totally Unique Recording Device (T.U.R.D.)
8. Orchard Dynamic Class Extensions
Extending the BlogPost content type dynamically
Metatag addition to page head example:
1.<meta content="Orchard is an open source Web
CMS built on ASP.NET MVC."
2. name="description" />
3.<meta content="Orchard, CMS, Open source"
name="keywords" />
Module will add the above properties to the head section of
the Blog Post Page
Used to facilitate Search Engine Optimization
A previously unavailable Content Part
9. Orchard Dynamic Class Extensions
Extending the BlogPost content type dynamically
Building a new Content Part via a Module
-The Record
-The Part Class
-The Driver
These are basic components to a Content Type Module
10. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Record
0. public class MetaRecord :
ContentPartRecord {
0. public virtual string Keywords { get; set;
}
1. public virtual string Description { get;
set; }
2. }
Deriving from ContentPartRecord not absolutely necessary
A Record provides object persistence in the database
Virtual properties enables dynamic mix-in
11. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Record
1.public class MetaHandler :
ContentHandler {
2. public MetaHandler(
3. IRepository<MetaRecord> repository)
{
4. Filters.Add(
5. StorageFilter.For(repository));
6. }
7.}
The record's only job is persistence.
Via a method, the Record table maps to the record class with calls to
the ContentPartRecord plus Keywords and Description String
Columns.
12. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Part Class
The representation of the part itself is another class that
derives from ContentPart<TRecord>:
1.public class MetaPart : ContentPart<MetaRecord> {
2. public string Keywords {
3. get { return Record.Keywords; }
4. set { Record.Keywords = value; }
5. }
6. public string Description {
7. get { return Record.Description; }
8. set { Record.Description = value; }
9. }
10.}
13. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Part Class
-Part acts as proxy to Keywords and Description properties, but
can be accessed through base ContentPart class.
-Strong typing of of Keywords and Descriptions enabled by As
method (analog to CLR cast operation):
1.var metaKeywords = item.As<MetaPart>().Keywords;
-Part class can be a composite; exposing subobject methods or
composite properties.
14. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Driver
-Class derived from CotentPartDriver
-Scaled-Down Controller
-Methods handling well-defined events
-Display
-Editor
15. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Driver
Sample Driver for metadata display method -
1.protected override DriverResult Display(
2. MetaPart part, string displayType, dynamic shapeHelper) {
3. var resourceManager = _wca.GetContext
().Resolve<IResourceManager>();
4. if (!String.IsNullOrWhiteSpace(part.Description)) {
5. resourceManager.SetMeta(new MetaEntry {
6. Name = "description",
7. Content = part.Description
8. });
9. }
10. if (!String.IsNullOrWhiteSpace(part.Keywords)) {
11. resourceManager.SetMeta(new MetaEntry {
12. Name = "keywords",
13. Content = part.Keywords
14. });
15. }
16. return null;
17.}
16. Orchard Dynamic Class Extensions
Building a new Content Part via a Module
-The Driver
-Most Drivers return a Dynamic Object called a shape
-Shapes are assembled by Orchard into a composite and
dynamic view model for the entire request.
-Default rendering can be overriden by inserting a file into
the current theme.
17. Orchard Dynamic Class Extensions
Key Questions -
Why does Orchard have virtual methods?
What does it mean to dynamically extend a class at
runtime?
Why dynamically extend a class at runtime?
How do I dynamically extend a class at runtime?
18. Orchard Dynamic Class Extensions
Thank You!
Mark Dolar Contact Info:
Linkedin:
http://www.linkedin.com/pub/mark-dolar/0/95/344
Follow Mark’s Little Media Blog via Twitter – More
Common Sense than one Blog should enjoy:
Twitter Name: Powerfinger
Current Topic: The Top Ten Reasons We Need Big Data
19. Orchard Dynamic Class Extensions
Thank You!
Nesim Sisa Contact Info:
Linkedin:
http://www.linkedin.com/pub/nesim-sisa/41/911/540
Email:
Nesim.Sisa at gmail.com
Notas del editor
No matter what CMS you use to build your site, there will be a central content entity that goes by different names. In Drupal, it’s called a node, and in Orchard, it’s a content item. Content items are atoms of content such as blog posts, pages, products, widgets or status updates. Some of them correspond to a URL, and some don’t. Their schemas vary greatly, but what they have in common is they’re the smallest content units on the site. Or are they?As developers, our first reaction is to identify content items as instances of classes (post, page, product or widget), which is correct to an extent
Question 1 certainly falseSome of them correspond to a URL, and some don’t. Question 2 may be true or false, depending on whether the Closed Captioning is being processed by a video player run by a driver. If the Closed Captioning is processed independent of the video, it could be it’s own content part (ie. A search algorithm).Question 3 probably false (requires a module). Content Types can be added without developmentQuestion 4 I think is true
Question 1 is obviousQuestion 2 is probably true, but should initiate discussion. In other words, I can’t describe a Blog Posting because the definition is not universal. It turns out there are only two fields: Keywords and Descriptions and two methods: Display and Editor.
There's not much Here...by designNo Comments or Tags
The objective is to extend the capabilities of the Blog Post Content Type – is a new Content Type created?Figure 2 The SEO Meta Data EditorThese properties will be rendered into the head section of the page as standard metatags that search engines understand:<meta content="Orchard is an open source Web CMS built on ASP.NET MVC."name="description" /><meta content="Orchard, CMS, Open source" name="keywords" />
If you want to build a module, you will likely need each one these. One of them is optional – which one?
That is basics of the Record
The Part Class basically contains two properties – Keywords and Description
Now we get to some interesting stuff –The part acts as a proxy to the record’s Keywords and Description properties as a convenience, but if it didn’t, the record and its properties would still be available through the public Record property of the base ContentPart class.Any code that has a reference to a content item that has the MetaPart part will be able to gain strongly typed access to the Keywords and Description properties by calling the As method, which is the analog in the Orchard type system of a CLR cast operation:varmetaKeywords = item.As<MetaPart>().Keywords;The part class is also where you’d implement any specific behavior of the part’s data. For example, a composite product could expose methods or properties to access its subproducts or compute a total price.Behavior that pertains to user interaction (the orchestration code that would in a regular ASP.NET MVC application be found in the controller) is another matter. This is where drivers come in.
Each part in a content item has to get an opportunity to participate in the request lifecycle and effectively do the work of an ASP.NET MVC controller, but it needs to do it at the scale of the part instead of doing it at the scale of the full request. A content part driver plays the role of a scaled-down controller. It doesn’t have the full richness of a controller in that there’s no mapping to its methods from routes. Instead, it’s made of methods handling well-defined events, such as Display or Editor. A driver is just a class that derives from ContentPartDriver.
Prepares the Rendering of the Part (extra precaution due to shared header region)
By calling in to all the drivers for all the parts, Orchard is able to build a tree of shapes—a large composite and dynamic view model for the whole request. Its next task is to figure out how to resolve each of the shapes into templates that will be able to render them. It does so by looking at the name of each shape (Parts_Meta_Edit in the case of the Editor method) and attempting to map that to files in well-defined places of the system, such as the current theme’s and the module’s Views folders. This is an important extensibility point because it enables you to override the default rendering of anything in the system by just dropping a file with the right name into your local theme.