Skip to content

了解内容处理程序-Understanding Content Handlers

This topic has been updated for the Orchard 1.9.1 release.

本主题已针对Orchard 1.9.1发行版进行了更新。

A content handler defines what happens with a content part in response to specific events, such as when the part is activated. The content handler enables you to perform actions at particular moments in the lifecycle of the content item. It also enables you to set up data repositories and manipulate the data model prior to rendering the content item.

内容处理程序定义内容部分响应特定事件时发生的情况,例如激活部件时。内容处理程序使您可以在内容项的生命周期中的特定时刻执行操作。它还使您能够在呈现内容项之前设置数据存储库并操纵数据模型。

Typically, you define a handler for a content part by creating a class that inherits from ContentHandler. The ContentHandler class is a base class that provides the methods and properties you will commonly need when defining your own content handler. Alternately, you can also create your own content handler by creating a class that implements IContentHandler.

通常,您可以通过创建继承自“ContentHandler”的类来为内容部件定义处理程序。 ContentHandler类是一个基类,它提供了在定义自己的内容处理程序时通常需要的方法和属性。或者,您也可以通过创建实现IContentHandler的类来创建自己的内容处理程序。

Defining Data Repository and Adding Filters

定义数据存储库和添加过滤器

When working with a content part that persists data, add a constructor for the handler that accepts an IRepository parameter for objects of the type you defined for records in the part. The following code shows a basic implementation of a content handler. MapRecord is a class defined in a separate file.

使用持久化数据的内容部件时,为处理程序添加构造函数,该构造函数接受为您为部件中的记录定义的类型的对象的“IRepository”参数。以下代码显示了内容处理程序的基本实现。 MapRecord是在单独的文件中定义的类。

using Map.Models;

using Orchard.ContentManagement.Handlers;

using Orchard.Data;



namespace Map.Handlers {

    public class MapHandler : ContentHandler {

        public MapHandler(IRepository<MapRecord> repository) {

            Filters.Add(StorageFilter.For(repository));

        }

    }

}

You can add other types of filters to the content handler. For example, you can add an ActivatingFilter to the Filters collection to define how the part is added to a type.

您可以向内容处理程序添加其他类型的过滤器。例如,您可以将ActivatingFilter添加到Filters集合中,以定义如何将零件添加到类型中。

Built-in filter types

内置过滤器类型

  • StorageFilter class - Takes care of persisting the data from repository object to the database. Its usage is shown in the example above.

  • StorageFilter类 - 负责将来自repository对象的数据持久保存到数据库中。其用法如上例所示。 *

  • ActivatingFilter class - Attaches a part to a content type from code. As opposed to attaching parts via migrations, parts attached using this filter will neither be displayed in the Dashboard, nor users will be able to remove them from types. It's a legitimate way of attaching parts that should always exist on a given content type.

  • ActivatingFilter类 - 从代码中将一部分附加到内容类型。与通过迁移附加零件相反,使用此过滤器附加的零件既不会显示在仪表板中,也不会将用户从类型中删除。这是一种合法的方式来附加应该始终存在于给定内容类型上的部分。

Lifecycle Events

生命周期事件

In addition to defining the repository, you can add code for handling events. You use the following methods to add the code that is executed for the event:

除了定义存储库之外,您还可以添加用于处理事件的代码。您使用以下方法添加为事件执行的代码:

  • OnActivated

  • OnActivated *

  • OnCreated

  • OnCreated *

  • OnCreating

  • OnCreating *

  • OnDestroyed

  • OnDestroyed *

  • OnDestroying

  • OnDestroying *

  • OnGetContentItemMetadata

  • OnGetContentItemMetadata *

  • OnGetDisplayShape

  • OnGetDisplayShape *

  • OnGetEditorShape

  • OnGetEditorShape *

  • OnIndexed

  • OnIndexed *

  • OnIndexing

  • OnIndexing *

  • OnInitialized

  • OnInitialized *

  • OnInitializing

  • OnInitializing *

  • OnLoaded

  • OnLoaded *

  • OnLoading

  • OnLoading *

  • OnPublished

  • OnPublished *

  • OnPublishing

  • OnPublishing *

  • OnRemoved

  • OnRemoved *

  • OnRemoving

  • OnRemoving *

  • OnUpdated

  • OnUpdated *

  • OnUpdateEditorShape

  • OnUpdateEditorShape *

  • OnUpdating

  • OnUpdating *

  • OnUnpublished

  • OnUnpublished *

  • OnUnpublishing

  • OnUnpublishing *

  • OnVersioned

  • OnVersioned *

  • OnVersioning

  • OnVersioning *

For example, the TagPartHandler class contains code to take action for the Removed and Indexing events, as shown in the following example:

例如,TagPartHandler类包含对RemovedIndexing事件采取操作的代码,如以下示例所示:

public class TagsPartHandler : ContentHandler {

    public TagsPartHandler(IRepository<TagsPartRecord> repository, ITagService tagService) {

        Filters.Add(StorageFilter.For(repository));



        OnRemoved<TagsPart>((context, tags) =>

            tagService.RemoveTagsForContentItem(context.ContentItem));



        OnIndexing<TagsPart>((context, tagsPart) =>

            context.DocumentIndex.Add("tags", String.Join(", ", tagsPart.CurrentTags.Select(t => t.TagName))).Analyze());

    }

}

Data Manipulation

数据操作

You can override the following methods to perform actions related to the state of the data:

您可以覆盖以下方法以执行与数据状态相关的操作:

  • GetItemMetadata

  • GetItemMetadata *

  • BuildDisplayShape

  • BuildDisplayShape *

  • BuildEditorShape

  • BuildEditorShape *

  • UpdateEditorShape

  • UpdateEditorShape *

For example, the BlogPostPartHandler class overrides the GetItemMetadata method to add route values using code like the following:

例如,BlogPostPartHandler类重写了GetItemMetadata方法,使用如下代码添加路由值:

protected override void GetItemMetadata(GetContentItemMetadataContext context) {

    var blogPost = context.ContentItem.As<BlogPostPart>();



    if (blogPost == null)

        return;



    context.Metadata.CreateRouteValues = new RouteValueDictionary {

        {"Area", "Orchard.Blogs"},

        {"Controller", "BlogPostAdmin"},

        {"Action", "Create"},

        {"blogId", blogPost.BlogPart.Id}

    };

    context.Metadata.EditorRouteValues = new RouteValueDictionary {

        {"Area", "Orchard.Blogs"},

        {"Controller", "BlogPostAdmin"},

        {"Action", "Edit"},

        {"postId", context.ContentItem.Id},

        {"blogId", blogPost.BlogPart.Id}

    };

    context.Metadata.RemoveRouteValues = new RouteValueDictionary {

        {"Area", "Orchard.Blogs"},

        {"Controller", "BlogPostAdmin"},

        {"Action", "Delete"},

        {"postId", context.ContentItem.Id},

        {"blogSlug", blogPost.BlogPart.As<RoutePart>().Slug}

    };

}