src/docs/releases/1.7.0.md
Release date: September 2023
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.OrchardCore.AdminDashboard ModuleA 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 Tools → Recipes
OrchardCore.Users ModuleAdded 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.
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 ModuleThe Seo feature now provides robots.txt out of the box when the filesystem does not contain one. New settings are available at Settings → Search → Search Engine Optimization → Robots 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 ModuleThe 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.
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 ModuleA 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 ModuleDue 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 ModuleThe OpenId module is now also enabling plain code challenge method by default. S256 remains the recommended choice.
OrchardCore.Sms ModuleNew feature was added to provide a way to send SMS messages to the users. Click here for more info about SMS.
Two-Factor SMS Method FeatureThe new "Two-Factor SMS Method" feature, permits you to transmit a two-factor authentication code to the user using SMS services.
SMS Notifications FeatureAdded a new "SMS Notifications" feature to allow you to send user notifications using SMS services.
Media Indexing FeatureThe 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 ModuleWhen 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.