Detailed analysis of orchard's content, drivers, shapes and placement types

Source: Internet
Author: User

The original Article from: http://skywalkersoftwaredevelopment.net/blog/a-closer-look-at-content-types-drivers-shapes-and-placement

In this article, we will look at the concepts that enable me to stay awake at night, because my life cannot find out the concepts related to: shapes, content types, parts, fields, drivers and placement. If you have some experience using orchard but still feel a little clumsy about shapes, this article is prepared for you.

First, let's take a look at how orchard presents content when a user's request (request) arrives, and how drivers and placement draw pages and shapes content (value) how is it converted to HTML and sent to the user concurrently.

This article is intended for those module and topic developers who have some experience in using drivers, content, shapes, and placement and want to learn more about how they work.
If you are ready, let's start with shapes.

1. What is shape?

So what is shape? What is the shape of an object we usually talk about? For example, the shape of the earth is like an elliptical shape, while the pyramid of Egypt is a cone-structured Polygon Shape. What does the word shape mean? Does orchard's "shape" mean ?, Well, shape is a dynamic object of an instance class or a static class. We can append all kinds of information to the shape at runtime, or even add a list. Essentially, we can shape what we want. I think "shape" is the dynamic shape ability of an object (Note: shape is intended to be a shape, but the word "Chinese shape" cannot fully express the meaning of shape. shape not only includes the appearance, there are also the data to be dyed and the method to perform the dyeing. For example, channel shape in WCF means this, if the shape of orchard can still be visually perceived, channel shape is just a concept to implement a specific message exchange mode ). The shape class looks like:

1: Public class shape: composite, ishape, ienumerable <Object> {
2: Public shapemetadata metadata {Get; set ;}
3: Public ID {Get; set ;}
4: Public ilist <string> classes {Get ;}
5: Public idictionary <string, string> attributes {Get ;}
6: Public ienumerable <dynamic> items {Get ;}
7:
8: Public Virtual shape add (Object item, string position = NULL ){}
9: Public Virtual shape addrange (ienumerable <Object> items, string position = "5 "){}
10: ienumerator <Object> ienumerable <Object>. getenumerator (){}
11: Public Virtual ienumerator getenumerator (){}
12: Public override bool tryconvert (convertbinder binder, out object result ){}
13: Public override bool trysetindex (setindexbinder binder, object [] indexes, object Value ){}
14: Public override bool tryinvokemember (invokememberbinder binder, object [] ARGs, out object result ){}
15 :}

Its magic is that we can use shape to implement ienumerable <Object> (we can traverse the sub-shape), through the tryinvokemember method, call an inline key-Value Pair Dictionary (called the composite class implemented by the Base class of shape). When you call tryinvokemember, you can obtain a dynamically implemented shape. The code can be written as follows:

1 :@{
2: var mysampleshape = new. mysampleshape ();
3: mysampleshape. color = "green ";
4 :}

Row 3: A new shape is created through the shape factory class. The new property is stored in the view, and the new property is of the dynamic type.
Row 3 sets a color attribute for the newly created shape. When we execute the code, we use tryinvokemember to query the value of a dictionary named "color.

This is rather intelligent.

The following article has some interesting additional information about shape: Using shapes as HTML helpers in orchard. http://www.szmyd.com.pl/blog/using-shapes-as-html-helpers-in-orchard

Now that we know more about shape, let's talk about what they are used. The answer is simple: Of course, it is the purpose of rendering. But what exactly does this mean?

Ii. Rendering shape-naming syntax

When we talk about rendering a shape, we really mean: using the shape object model to present a razor view ,. The rendering operation results in a string sent to the HTTP Response output, just as the razor view rendering razor view engine does. But how does orchard know how razor treats shape rendering ?, Which available razor views can we control? Yes, the answer is the shape metadata (metadata) attribute (Note: A shapemetadata type metadata attribute ). The string attribute of the metadata object is called a type and may be similar to "mysampleshape ". Based on this name, orchard instructs the razor view engine to find a view named "mysampleshape. cshtml" and use the shape model to execute this view. The metadata attribute also has an ilist <string> set called the alternates (substitution) attribute, which will be discussed later.

It is important to know that you must use the C # member and variable naming rules to name the shape. The reason for this is that we can create a shape, just like the shape factory method name (as we have seen before), without specifying its name as a string value, when the static type is used as the shape factory of ishapefactory (details will be given later ). We can create a shape, as if we were calling a method. For example, the following is a valid shape Name:

Mysampleshape
My_sample_shape
My _ sample_shape

The following is an invalid Name:

My. Sample-shape
My_Sample-Shape
My-sampleshape

These are invalid because these names are not compiled in C.
  
However, orchard developers may not like to forcibly use such a file name (which should be the case), so they come up with an agreed shape type name mapped to the file name of the razor view.
The conventions are as follows:

1. A single underscore (_) is replaced with a dot (.).
2. The Double underline "_" is replaced with a hyphen (-).

So if you have a shape named my_sample _ shaperazor file, you should look for "My. Sample-Shape.cshtml ".

3. Where does shapes come from?

Where does shape actually come from? How is it created? How do we create them ourselves? The answer to these questions is: shape is created by an implementation class called the ishapefactory interface.

As we can see, in a razor view, you can access new attributes through each shape factory inherited from the razor view. The new property is the static type of dynamic, but it is an instance that implements the ishapefactory class. The new property type is dynamic because it is easier to process through the shape factory. For example, if you have an ishapefactory static class, the following code demonstrates how to create a shape: (Note: The following code should be placed in a razor file. You can select the layout. cshtml file of your topic. The new factory method is a method of the webviewpage class of orchard. MVC. viewengines. Razor );
1 :@{
2:
3: var shapefactory = (ishapefactory) New; // create a new ishapefactory for demonstration
4:
5: var myshape = (dynamic) shapefactory. Create ("mysampleshape", parameters. From ({
6: myproperty1 = "some property value ",
7: myproperty2 = 42
8 :}));
9:
10 :}

Compare the following when we work as a dynamic shape Factory:
1 :@{
2:
3: var shapefactory = new;
4:
5: var myshape = shapefactory. mysampleshape (
6: myproperty1: "Some property value ",
7: myproperty2: 42
8 :);
9:
10 :}

Although the number of lines of code is the same, the syntax is simpler and looks better. Note that we can create a shape just like the "mysampleshape" method on shapefactory. Of course not ), however, the shape factory implements its dynamic behavior interception method call and creates a shape based on the called method name. Its parameters and their features become the shape feature. Very clean.

So it is: shape comes from ishapefactory. You can create a shape as long as you have an ishapefactory. The razor view accesses the new attribute of the Shape factory and injects your own code through ishapefactory.

4. Rendering shape-alternates (alternative)

We briefly mention shape alternates. What are them? Technically, they are just a string list that stores metadata in a shape alternates attribute. When orchard is about to instruct the view engine to look up the view, it checks whether all alternates have a view that matches it. Orchard applies the same shape name ing syntax. The Razor View File name syntax is described above. Then fill in the alternates list? The answer is: Any alternates code can be added to the shape object. The so-called shape table providers is usually used for operations.

5. Shape table providers

Shape table providers is a class that implements the ishapetableprovider interface and attaches the event handler to shape. Possible shape events:

1. Creating
2. Created
3. Displaying
4. displayed

Generally, a display event handler is provided, and the shape of alternates can be added to this handler. Let's take a look at a simple example.
First, let's imagine creating a shape with the color attribute. Our purpose is to provide two razor views that can be used when rendering a shape. The used view should be based on the color value of the shape. The shape created and rendered looks like this:

1 :@{
2: var mybluecoloredshape = new. colorshape (color: "blue ");
3: var myredcoloredshape = new. colorshape (color: "red ");
4 :}
5:
6: @ display (mybluecoloredshape)
7: @ display (myredcoloredshape)

To make the code work, we should create at least one view file with a name that matches the colorshape. Let's create a default view to display the specified color:

Views/colorshape. cshtml:
1 :@{
2: var color = model. color;
3 :}
4: <p> my color is: @ color </P>

See colorshape. how does the cshtml view access the color attribute in the model? When we call @ display through shape, the orchard view engine searches for the View File and executes the view model through shape.

Now, we want to use a completely different view file based on color. To this end, we create a new class file in our module as follows:

1: Public class colorshapetableprovider: ishapetableprovider {
2: Public void discover (shapetablebuilder builder ){
3: builder. Describe ("colorshape ")
4:. ondisplaying (displaying => {
5: var shape = displaying. shape;
6: var color = shape. color;
7:
8: Displaying. shapemetadata. alternates. Add (string. Format ("colorshape __{ 0}", color ));
9 :});
10 :}
11 :}

The first thing we do is "describe" (description) shape (row 3rd), which indicates "configure the following shape ".
We configure a special handler that calls the ondisplaying method when orchard is about to render our shape. If you are confused about this table, you don't have to worry about overwriting other Event Handlers. The API will register multiple configuration items for shape and work well.

Please note that we can access our shape and color attributes (6th rows ). Use the value of this property to generate another shape and add it to the metadata aternates set (8th rows ).

Matching with the shape table provider, we can now create the following two view files:

1. ColorShape-Blue.cshtml
2. ColorShape-Red.cshtml

With this processing method, orchard becomes better used. For example, you can render content shapes by providing content-based content type names and alternates of the display type used. We will discuss it in more detail later.

We have seen how to create a display rendering method that uses the shape factory and inherits from each view. Before proceeding, I want to show that you can create and render the custom shape in a row. It looks like this:

1: @ display. colorshape (color: "yellow ")

In this way, you only need to create one row!

6. Add shapes to the Zone)

This is cool! We have a better understanding of what shape is and how they work. Facts have proved that this is not to say that it is complicated (note: this refers to the auxiliary class work that needs to be created in the previous line, but to be added ).

Let's talk about zone. In orchard, when we talk about zones, we are talking about items that can be fixed in some views (normally in layouts. cshtml. So what is this thing?

Dear students (note: the original article is so ^ o ^), it turns out that zone is just another shape. The only difference is that it inherits the class called zoneholding (Note: defined in Orchard. UI. zoneholding is inherited from shape. Soon we will see why this is important.

We usually talk about global zones and local zones. The region defined in root-of-all-shapes defines a global zone and a layout shape. Orchard creates this shape for us and can be accessed in each view through the workcontext attribute.

If you are modifying the view layout shape, you can directly access these zones through the model attribute of the view. Again, when you want to add shapes from the layout shape zones of other views, you can access the workcontext object of the layout shape.

Views/layout. cshtml
1 :@{
2: // create a new shape.
3: var mysampleshape = new. sampleshape ();
4: // Add the shape to asidesecond Zone
5: // This is a layout shape view.
6: // Therefore, we can access layout shape through the model attribute of the view.
7: // instead of accessing layout shape through workcontext. Layout
8: // because in the layout. cshtml view, model = workcontext. Layout
9: model. asidesecond. Add (mysampleshape );
10 :}
11:
12: @ * present the view to asidesecond zone somewhere *@
13: @ display (model. asidesecond)

The above code will create an example shape (Make sure you create a corresponding View File), add it to a region called asidesecond, and then display the zone. The result is that the sample shape is displayed in asidesecond zone.

VII. zoneholding

So there is a question: can we name any region, or do we have to define them in some way?

In fact, layout shape is a special type of shape, called zoneholding shape. The zoneholding class comes from the shape class and uses the shape that creates a dynamic layout of the zone shape as the access attribute.

Thank God zoneholding shape type, which will automatically complete for us.

But is it like-why is it possible to create a zone in the theme(theme.txt) file?

Very good question. The reason for this is that the region name we specified in the topic list does not actually mean that we can present it in any region. On the contrary, this list is the zone section used to render widgets. For example, let's look at thethememachine.
The theme.txt file defined by the following region Name:
Header, navigation, featured, beforemain, asidefirst, messages, beforecontent, content, aftercontent, asidesecond, aftermain, tripelfirst, tripelsecond, marker, footerquadfirst, footerquadsecond, marker, marker, footer

These region names will cause them to appear on the widgets configuration page:



When you create a widgets and add it to a region, the code that shows the widgets is actually using the storage region name to add the widgets shape region. Very good.

8. rendered content (rendering content)

Now we have seen what shape is and how we use and render it, so that we can really study how to present a content item. To better understand how to present a content item, we must have a deep understanding of what drivers and content handlers are and what role placement.info plays.

9. in-depth understanding of content item (Anatomy of a content item)

A content item is basically composed of the following:

1. It has a content type: the content type is essentially a content item Blueprint (blueprint ). For example, for the page content type, it has a professional name called "page" and a display name (also known as a friendly name) called "page ".

2. It has a set of Content Parts.
For example:
1) titlepart
2) bodypart

These Content Parts define the data and behavior of the content type of the content item.

Therefore, a page content item is a content item with a "page" and copies Content Parts of the content type. An important feature of content parts is that any given content type can only have one instance of the same content parts type. For example, there can be multiple titleparts without a content item. However, content items can have both titlepar and bodypart.

Parts can own attributes. For example, titlepart has a title attribute type string, while the bodypart text attribute type string.

In addition, all parts set attributes are called fields, which is a content fields set. Compared with content item, content parts can have many content of the same type of fields. Examples of content fields:

Text Field
Boolean Field
Media Library picker Field
Taxonomy Field
Date time field
Content picker Field
Enumeration Field

You can use the control panel (Orchard Management backend) to add content parts to the content type and content parts to add content fields. To add a property to the content section, the developer must create a class C # With the professional name of the content part.

The following is a simple tree view that shows the level of content, its parts, fields of each parts, and the structure of content items. It is essentially the same content type:



As you can see, a content type can have multiple parts, and each part can have multiple fields.

Now let's use code to create a new page content item and use view to render it as we thought. We need a controller and an action, which looks like the following:

Controller:

1: Public class itemcontroller: controller {
2: Private icontentmanager _ contentmanager;
3:
4: Public itemcontroller (icontentmanager contentmanager ){
5: _ contentmanager = contentmanager;
6 :}
7:
8: Public actionresult display (int id ){
9: var contentitem = _ contentmanager. Create ("page", versionoptions. published );
10: var titlepart = contentitem. As <titlepart> ();
11: var bodypart = contentitem. As <bodypart> ();
12:
13: titlepart. Title = "Hello Orchard ";
14: bodypart. Text = "<p> welcome to my new page! </P> ";
15:
16: Return view (contentitem );
17 :}
18 :}

View:
1 :@{
2: var contentitem = (contentitem) model; // access content item through model
3:
4: // get a reference titlepart and bodypart, so that we can render them correctly.
5: var titlepart = (titlepart) contentitem. As <titlepart> ();
6: var bodypart = contentitem. As <bodypart> ();
7 :}
8:
9: 10: @ html. Raw (bodypart. Text)

As we can see in the first code snippet, create a new content item content type "page" and access its titlepart, bodypart and some initialize their values, finally, the view of the model of a content item is returned.

The second code snippet shows how we can access the content items of two parts through their attribute values.

Very simple. However, there is a warning: code like this requires hard encoding of content items. However, the real strength of orchard is that you can attach reusable content parts and fields to any content type without creating a specific view for these content types. How to do it? The answer is: let each content part and content fields decide how to render it.

10. Content Part and field drivers

A long time ago, the orchard people came up with an API that can be used as an input content item and return a shape as the output. Shape can be rendered. This API icontentmanager is implemented as a method called builddisplay and its signature is as follows:

1: /// <summary>
2: // builds the display shape of the specified content item
3: /// </Summary>
4: // <Param name = "content"> the content item to use </param>
5: // <Param name = "displaytype"> the display type (e.g. Summary, detail) to use </param>
6: // <Param name = "groupid"> ID of the display group (stored in the content item's metadata) </param>
7: // <returns> the display shape </returns>
8: Dynamic builddisplay (icontent content, string displaytype = "", string groupid = "");

The default Implementation of icontentmanager (defaultcontentmanager) is not much. On the contrary, it represents the shape of the icontentdisplay instance.

At a high level, this is the default Implementation of icontentdisplay:

1. Create a new content type with the same shape as stereotype. By default, this is a "content", and a new "content" shape type will be created. The base class of this shape is zoneholding, so zone shapes and layout shape can be automatically created.

2. The displaytype parameter of shape is set to any display type. This display type is used to provide an alternative based on this display type. If no display is specified, "detail" is used ".

3. Implement contenthandler called by builddisplay.
 
4. Two contenthandler implementations are provided to implement the content part Driver System: contentpartdrivercoordinator of the content part and contentfielddrivercoordinator of the content fields. These handlers aim to traverse the content items of each part and fields and find their driver. For each found driver, the builddisplayshape method calls its protected display method when called. Its implementation is implemented by the specific driver.
 
5. This specific display implementation will eventually return driverresult, which is usually an instance of contentshaperesult. Contentshaperesult holds the name of a rendered shape, and creates a shape rendering shape factory method. This document demonstrates the implementation of a content part driver example.

6. Note that the driver returns the value of content shape with the name of the rendered shape, and creates the actual shape and reference method. The reason we do not return the created shape immediately is that if we decide not to render it to some extent, we do not need to create a shape. There is a system called placement that determines where the shape should be rendered or does not render it at all. We will discuss this soon, but I would like to say that this is why we provide the shape NAME AND SHAPE factory methods respectively (so the shape is bound late ).
 
7. When the display method of each driver is called, The Calling Code determines the place where the shape needs to go, if it needs to be rendered. Will read the placement.info XML file, which contains the shape name and location information. For example, if a driver returns a shape named "parts_title", the placement.info file has an element such as <place parts_title = "header: 1"/>, the shape is called the "Header" position in a zone. This shape will be created in step 1st of shale.
 
What we finally get is the shape of an item, all having hierarchical parts and field shapes. What orchard needs to do is to make this shape and then render its child shape. As you can see, this is very powerful. Each part and field only cares about rendering itself, and placement.info is used to externally control where these shapes should be displayed. This is especially powerful, and you can cover the placement.info topic to meet different needs.

The following is the drive, controller, view, and rendered shape of the content module (orchard. Core found) of the Code Execution path itemcontroller in a flowchart:



I don't know what you feel, but I'm excited when I finally can use my head through drivers in the pipeline requesting content items (when requesting to use its route, because the rendering pendant widgets is from an actionfilter instead of a controller. But it is all the same process), and understanding the shape can really come from anywhere: from the Controller controllers, drivers, Action filters, or even from the view (also known as a special shape ).
 

 

Detailed analysis of orchard's content, drivers, shapes and placement types

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.