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 along
.Task<long> ElasticIndexManager.GetLastTaskId(string indexName)
, now returns along
.
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:
-
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 ValueTask.FromResult<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 ValueTask.FromResult<IQuery<User>>(filteredQuery); } ) ); } }
-
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:
-
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)) ) ) ); } }
-
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
.