Skip to content

Orchard Core 1.7.0

Release date: September 2023

Breaking Changes

The database identity columns' size is now configurable. This applies to both the Id column in all tables and the DocumentId column in all index tables. Consequently, the corresponding fields in entities and map indexes associated with these columns have been changed from an int type to a long type.

Note

If your project contains custom entities and/or map indexes with similar fields, it is recommended to update them accordingly.

Here is a list of the fields that were changed.

  • ContentItem.Id.
  • DataMigrationRecord.Id.
  • IndexingTask.Id.
  • User.Id.
  • DeploymentPlan.Id.
  • Workflow.Id.
  • WorkflowType.Id.
  • WorkflowEntry.Id.
  • WorkflowTypeEntry.Id.
  • OpenIdApplication.Id.
  • OpenIdAuthorization.Id.
  • OpenIdScope.Id.
  • OpenIdToken.Id.
  • ContentItemIndex.DocumentId.
  • AutoroutePartIndex.DocumentId.
  • AutorouteEntry.DocumentId.
  • LocalizedContentItemIndex.DocumentId.
  • LocalizationEntry.DocumentId.
  • UserIndex.DocumentId.
  • DeploymentPlanIndex.DocumentId.
  • WorkflowIndex.DocumentId.
  • WorkflowTypeIndex.DocumentId.

The YesSql.ISession.GetAsync<T>(int id, ...) has already been updated to GetAsync<T>(long id, ...), this was not a breaking change as an implicit convertion is done as needed but it is recommended to now pass a long id parameter. The ISession.GetAsync<T>(int[] ids, ...) has already been updated to GetAsync<T>(long[] ids, ...), for backward compatibility an extension method still accepting an int[] array has been created but it is recommended to use the method of the updated ISession interface.

So, the following interfaces and implementations methods using these YesSql methods directly or not and having the same kind of parameters have been updated. For backward compatibility extensions still accepting a collection of int ids have been created but it is recommended to use the methods of the updated interfaces.

Note

If you have custom implementations using the following methods, it is recommended to update them accordingly, and to change the signature of methods having an int id or a collection of int ids parameter so that they accept a long id or a collection of long ids instead.

  • Task<T> ISession.GetAsync<T>(long id, string collection = null), updated extension method.
  • Task<IEnumerable<T>> ISession.GetAsync<T>(long[] ids, string collection = null), updated interface method.
  • Task<IEnumerable<T>> ISession.GetAsync<T>(int[] ids, string collection = null), not recommended extension method.
  • bool IContentManagerSession.RecallVersionId(long id, out ContentItem item), updated interface method.
  • Task<IEnumerable<IndexingTask>> IIndexingTaskManager.GetIndexingTasksAsync(long afterTaskId, int count), updated interface method.
  • Task<Workflow> IWorkflowStore.GetAsync(long id), updated interface method.
  • Task<IEnumerable<Workflow>> IWorkflowStore.GetAsync(IEnumerable<long> ids), updated interface method.
  • Task<IEnumerable<Workflow>> IWorkflowStore.GetAsync(IEnumerable<int> ids), not recommended extension method.
  • Task<WorkflowType> IWorkflowTypeStore.GetAsync(long id), updated interface method.
  • Task<IEnumerable<WorkflowType>> IWorkflowTypeStore.GetAsync(IEnumerable<long> ids), updated interface method.
  • Task<IEnumerable<WorkflowType>> IWorkflowTypeStore.GetAsync(IEnumerable<int> ids), not recommended extension method.
  • long LuceneIndexingState.GetLastTaskId(string indexName), now returns a long.
  • Task<long> ElasticIndexManager.GetLastTaskId(string indexName), now returns a long.

Change Logs

OrchardCore.AdminDashboard Module

A sample widget is no longer auto created when the OrchardCore.AdminDashboard feature is enabled. If you like to see a sample widget, you may do so by executing the "Admin Dashboard Widget Sample" recipe by using the admin menu and navigate to Configuration >> Recipes

OrchardCore.Users Module

Added support for complete two-factor authentication out of the box. Click here for more info.

A phone number is now supported in the UserStore and the User object.

Full-Text Search for Admin UI

Additional options have been introduced to enable control over the behavior of the full-text search in the administration user interface for users.

For instance, when a user performs a search, the default behavior is to check if the search terms are present in the NormalizedUserName column of the UserIndex table. However, what if a user wants to search for a user using other logic like First or Last name, which is not part of the UserName field?

With the newly added options, we can now allow searching for user based on either the username or any custom logic. To modify the default behavior, two steps need to be taken:

  1. Implement IUsersAdminListFilterProvider interface by defining a custom lookup logic. For example:

    public class FullnameUsersAdminListFilterProvider : IUsersAdminListFilterProvider
    {
        public void Build(QueryEngineBuilder<User> builder)
        {
            builder
                .WithNamedTerm("fullname", builder => builder
                    .ManyCondition(
                        (val, query, ctx) =>
                        {
                            var context = (UserQueryContext)ctx;
                            var userManager = context.ServiceProvider.GetRequiredService<UserManager<IUser>>();
                            var normalizedUserName = userManager.NormalizeName(val);
    
                            // The index name 'UserFullnameIndex' does not exists. 
                            // It is a custom index that you would create or use other custom index or logic.
                            var filteredQuery = query.Any(
                                (q) => q.With<UserIndex>(i => i.NormalizedUserName != null && i.NormalizedUserName.Contains(normalizedUserName)),
                                (q) => q.With<UserFullnameIndex>(i =>
                                   (i.FirstName != null && i.FirstName.Contains(val)) ||
                                   (i.LastName != null && i.LastName.Contains(val)) ||
                                   (i.MiddleName != null && i.MiddleName.Contains(val))
                                )
                            );
    
                            return new ValueTask<IQuery<User>>(filteredQuery);
                        },
                        (val, query, ctx) =>
                        {
                            var context = (UserQueryContext)ctx;
                            var userManager = context.ServiceProvider.GetRequiredService<UserManager<IUser>>();
                            var normalizedUserName = userManager.NormalizeName(val);
    
                            var filteredQuery = query.All(
                                (q) => q.With<UserIndex>(i => i.NormalizedUserName == null || i.NormalizedUserName.NotContains(normalizedUserName)),
                                (q) => q.With<UserFullnameIndex>(i =>
                                   (i.FirstName == null || i.FirstName.NotContains(val)) &&
                                   (i.LastName == null || i.LastName.NotContains(val)) &&
                                   (i.MiddleName == null || i.MiddleName.NotContains(val))
                                )
                            );
    
                            return new ValueTask<IQuery<User>>(filteredQuery);
                        }
                    )
                );
        }
    }
    
  2. Register the custom default term name as a search option by adding it to the UsersAdminListFilterOptions. For example:

    services.Configure<UsersAdminListFilterOptions>(options =>
    {
        options.TermName = "fullname";
    });
    

OrchardCore.Seo Module

The Seo feature now provides robots.txt out of the box when the filesystem does not contain one. New settings are available at Configuration >> Settings >> SEO to allow you to configure what should be included into the robots.txt file.

Note

If the Sitemaps feature is enabled, all sitemap indexes and sitemaps are added to the robots.txt by default.

OrchardCore.Contents Module

List Content Types by Stereotype

The Contents admin UI now provides a way to manage content items of content types that share the same Stereotype.

For example, lets say we want list all content items of a content types that use Test stereotype. To do that, add an admin menu item that directs the user to /Admin/Contents/ContentItems?stereotype=Test. Adding stereotype=Test to the URL will render the UI using any content type that has Test as it's stereotype.

Full-Text Search for Admin UI

Additional options have been introduced to enable control over the behavior of the full-text search in the administration user interface for content items.

For instance, consider a content type called Product. Currently, when a user performs a search, the default behavior is to check if the search terms are present in the DisplayText column of the ContentItemIndex for the content item. However, what if a user wants to search for a product using its serial number, which is not part of the DisplayText field?

With the newly added options, we can now allow searching for products based on either the display text or the serial number. To modify the default behavior, two steps need to be taken:

  1. Implement IContentsAdminListFilterProvider interface by defining a custom lookup logic. For example:

    public class ProductContentsAdminListFilterProvider : IContentsAdminListFilterProvider
    {
        public void Build(QueryEngineBuilder<ContentItem> builder)
        {
            builder
                .WithNamedTerm("producttext", builder => builder
                    .ManyCondition(
                        (val, query) => query.Any(
                            (q) => q.With<ContentItemIndex>(i => i.DisplayText != null && i.DisplayText.Contains(val)),
                            (q) => q.With<ProductIndex>(i => i.SerialNumber != null && i.SerialNumber.Contains(val))
                        ),
                        (val, query) => query.All(
                            (q) => q.With<ContentItemIndex>(i => i.DisplayText == null || i.DisplayText.NotContains(val)),
                            (q) => q.With<ProductIndex>(i => i.SerialNumber == null || i.SerialNumber.NotContains(val))
                        )
                    )
                );
        }
    }
    
  2. Register the custom default term name as a search option by adding it to the ContentsAdminListFilterOptions. For example:

    services.Configure<ContentsAdminListFilterOptions>(options =>
    {
        options.DefaultTermNames.Add("Product", "producttext");
    });
    

Now, when a user searches for a product's serial number in the administration UI, we will utilize the producttext filter instead of the default text filter to perform the search.

The UseExactMatch option in the ContentsAdminListFilterOptions class modifies the default search behavior by enclosing searched terms within quotation marks, creating an exact match search by default, this unless if the search text explicitly uses 'OR' or 'AND' operators.

OrchardCore.Facebook Module

A new feature called Meta Pixel was added to allow you to easily enable Meta Pixel tracking into your website

Due to Facebook's recent rebranding, all of the Facebook features have been renamed to Meta. This only concerns UI labels and documentation, but technical identifiers remain, so you shouldn't expect anything breaking. Here is a list of the naming changes:

Previous Name New Name
Facebook Meta Core Components
Facebook Login Meta Login
Facebook Social Plugins Widgets Meta Social Plugins Widgets

OrchardCore.Microsoft.Authentication Module

Due to Microsoft's recent rebranding, Azure AD has been renamed to Microsoft Entra ID. This only concerns UI labels and documentation, but technical identifiers remain, so you shouldn't expect anything breaking.

OrchardCore.OpenId Module

The OpenId module is now also enabling plain code challenge method by default. S256 remains the recommended choice.

New OrchardCore.Sms Module

New feature was added to provide a way to send SMS messages to the users. Click here for more info about SMS.

New Two-Factor SMS Method Feature

The new "Two-Factor SMS Method" feature, permits you to transmit a two-factor authentication code to the user using SMS services.

New SMS Notifications Feature

Added a new "SMS Notifications" feature to allow you to send user notifications using SMS services.

New Media Indexing Feature

The Lucene and Elasticsearch feature are capable of searching within PDF files because PDF files are indexed by default. As an enhancement, we added a new feature called Media Indexing which extends the media indexing capability to also encompass searching within files with the following extensions .txt, .md, .docx, and .pptx.

Media Module

When enabling both the Media and Content Fields features, you can attach a media field to your content. This feature enables you to link different types of media to your content. As an enhancement, we added a new property to MediaFieldSettings named AllowedExtensions, to allow you to define extensions, thereby restricting the permissible media file extensions for the field.

Info

The specified extensions within the MediaFieldSettings must be a subset of the globally allowed extensions defined in AllowedFileExtensions within MediaOptions.