Our blog contains the activity stream of Orchard Dojo: general news, new resources or tutorials are announced here.

Content Tree Module, Orchard Core Admin UI experience renewal survey - This week in Orchard (06/06/2025)

This time, you can see a fascinating demo of the Content Tree Module! But first, let's look at our other topics, like adding GraphQL support for querying content items by status from the Content Picker Field, fixing binding form input in the Coming Soon theme, and improving the Register User Task. Don't forget to fill out our Orchard Core Admin UI experience renewal survey to help shape the future of Orchard Core!

Featured tags

IIS
API
SMS
SEO
MCP
All tags >

Support multipart content type with email service, UNION and UNION ALL clause support - This week in Orchard (20/07/2021)

A new OrchardCore.Email.Core project, support multipart content type with email service, a brand new Orchard Core site using Stripe.Js and Azure Functions and many more are waiting for you in our upcoming post! Orchard Core updates New OrchardCore.Email.Core project We don't have an OrchardCore.Email.Core project that is something similar to feeds and other functionality. Now the default implementation of the ISmtpService is in its own project, that is the OrchardCore.Email.Core one. Support multipart content type with email service Right now when we send an email as HTML by checking the Does the Body contain HTML checkbox option on the email task it will be sent only in HTML. Some email software will often transfer these emails as plain text so we should provide also a plain-text version of the email for the email software to be able to use. This way, we can provide two different Body versions of the email. The solution could be that when the Does the Body contain HTML checkbox is checked we should have a second Body (plain-text) text field to provide the email as plain text. Check out the following email example below to see that the email now could contain an HTML version of the body and a plain text version of the body too. From: [email protected]: Fri, 25 Jun 2021 17:34:43 -0400Subject: TestMessage-Id: <OUJBALN63EU4.IS3IGSIZUPB3@skrypt>Sender: [email protected]: [email protected]: [email protected]: 1.0Content-Type: multipart/alternative; boundary="=-9nfRnDakF+Ib69kpAIdY3A=="--=-9nfRnDakF+Ib69kpAIdY3A==Content-Type: text/plain; charset=utf-8Test text--=-9nfRnDakF+Ib69kpAIdY3A==Content-Type: text/html; charset=utf-8<p>Test html</p>--=-9nfRnDakF+Ib69kpAIdY3A==-- You can achieve this by creating a new Email task in your workflow, put a tick in these two checkboxes and provide the body texts of the email message. Refactoring SelectPart Vue to make it reusable If you have multiple SelectParts on a page, (e.g. a Form FlowPart with multiple Select widgets), then only the first one will actually have a working editor in the edit page or will render options correctly on the display. It has to do with each of the generated SelectOptionsTable/Modal Vue components relying on the same template ID regardless of which widget content item ID they actually correspond to. And it wasn't a huge deal to reproduce this bug. You just needed to run the Blog recipe and turn on the Forms feature. This allows you to add multiple Select widgets to a form's FlowPart. Now, this issue has been fixed. UNION and UNION ALL clause support Now you have support for UNION and UNION ALL clauses in SQL queries. It's not the first time when we have new SQL contracts in the SQL parser. And the ShouldParseUnionClause test in the SqlParserTests.cs file is just about checking that the dialect is generated the correct UNION and UNION ALL which is common to every dialect we use. Demos Using Stripe.Js + Azure Functions with Orchard Core Real Estate end Development is a site that chooses Orchard Core to implement its web appearance. You can register and have a subscription and can also purchase some magazines. The site uses Azure Functions and Stripe.Js to create customers for example with all the necessary inputs. And the flow continues to create a new subscription to that user and so on. If you would like to see the site in action, check out the following demo on YouTube! News from the community Orchard Core articles on .NET Thailand .NET Thailand houses several articles regarding several topics around .NET. Here you can see nice articles about how can debug your code using Chrome DevTool, Visual Studio, or VS Code, or how you can work Docker. And the site also contains some articles about Orchard Core too! For example, you can read a nice one here about how to create a content type and a content item programmatically or how to create a custom Orchard Core module from scratch. Lombiq Helpful Libraries: ContentVersionNumberService The Lombiq Helpful Libraries consist of several various libraries that can be handy when developing for Orchard Core CMS, to be used from your own Orchard modules. This time we will see some helpful services and extensions regarding content item version numbers. Sometimes you may want to know the latest or the current version number of a given content item. To get the version ID, you need to create a new query and query the content items using the ContentItemIndex table and get the value of the ContentItemVersionId column from there. Using our GetLatestVersionNumberAsync and GetCurrentVersionNumberAsync methods from the default implementation of the IContentVersionNumberService interface, you can easily get the version IDs just by injecting this to your code and provide the ID of a content item. Or use the extension methods where you can get the version ID by providing an IContent. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 209 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here!

Source Browser, Content Request Culture Provider cookie setting - This week in Orchard (12/07/2021)

Fixing forms multi submit, set the cookie in the Content Request Culture Provider, Source Browser with Orchard Core, and many more coming this week! Orchard Core updates Set the cookie in the ContentRequestCultureProvider The ContentRequestCultureProvider allows you to switch the current culture based on the content item URL. If you have a site in French and English and you go on a page that contains a French content item, then the full request will go in French. This is what the RequestCultureProvider does, it assigns the current thread culture to the one that a content item is taken. The issue is the following. Assume you have a drop-down French and English to switch languages. Like you are, for instance, on the home page for English. And in the drop-down, you select French using the content picker. In this case, your whole navigation is back in French. Everything you will click should be in French now; the widgets, the content items, everything. But if you go to a page that is in English, the cookie is still for French, which means the next page that will open will assume you still want to be in French. This new option lets you switch the cookie to the culture of the content item you are watching. That means if you go to a content item with a different culture, your cookie will say: 'Oh, I want to be in this culture now, I don't want to be in the one that the drop-down selected before!'. By default, the ContentCulturePicker sets a cookie for the CookieRequestCultureProvider. This can be disabled in the Configuration -> Settings -> Localization -> Content Culture Picker settings page. The ContentRequestCultureProvider can set the cookie based on the ContentItem that matches the current URL. This setting can be edited in the Configuration -> Settings -> Localization -> Content Request Culture Provider settings page. Minor security issue: Internal File Path Disclosure An issue has been raised that the Media module can potentially expose internal file paths, letting a would-be attacker find out what OS the server is using and gaining knowledge about the file structure being used by the web application. If you open up the AdminController and check out the HttpPost version of the Upload action, you would see the following lines in the code that prints the path of the given file. The media file stores are supposed to catch all exceptions and rethrow them as a FileStoreException. The issue was the result contains the path, while it shouldn't. This issue has been fixed by now. Fix forms multi submit The idea here is that if you add the no-multisubmit class, then you can't submit a form twice. So when you double click, there won't be two POST requests, just a single one. And the issues that it triggered were like locking issues or concurrency issues like two content items use the same version and then two published versions. This is preventing issues like this. And you had to change every single form to prevent that. Document Static File Provider Feature and robots.txt for Tenants There is a Static File Provider feature that allows you to have custom static files served for each tenant differently. And in this case, whatever file you put under the App_Data\Sites\[Tenant]\wwwroot will be served in priority over the module's static files or the theme's static files. This way you can customize, for instance, a CSS for a tenant by putting it in this folder. If all tenants use the same theme, you can customize CSS or JavaScript by putting the files there. If you would like to read more about this, check out this updated page of the documentation. Demos Source Browser Source browser website generator that powers https://referencesource.microsoft.com, http://sourceroslyn.io, https://source.dot.net, and others. Create and host your own static HTML website to browse your C#/VB/MSBuild/TypeScript source code. Note that it does require an ASP.NET Core website for hosting (symbol index is kept server-side), so without ASP.NET Core the search function doesn't work. Dean Marcussen decided to build one for Orchard Core. And you can now browse the source code of Orchard Core using Source Browser. You can find the source code in the dm/orchardcore branch of this repository. If you would like to see a nice demo and discussion about this feature, don't forget to check out the following recording on YouTube! News from the community Lombiq Helpful Libraries: Contents Libraries The Lombiq Helpful Libraries consist of several various libraries that can be handy when developing for Orchard Core CMS, to be used from your own Orchard modules. This time we will see some helpful constants and extensions regarding contents. The CommonContentDisplayTypes static class contains values that can be used with IContentItemDisplayManager.BuildDisplayAsync or OrchardRazorHelperExtensions.DisplayAsync to safely select the correct display type. Here we have a BuildDisplayAsync method that loads the content item if the display type is not SummaryAdmin. As you can see, we could use the SummaryAdmin constant string here. The PublicationStatus enum can be used for instance to query content items based on the status of the content item. The WithContentItem extension method also uses these enums to filters a query to match the publication status in ContentItemIndex. You can see we have a query.WithContentItem(PublicationStatus.Published) call that will extend the given query with the ContentItemIndex index and use the given status of the content item. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 207 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

Scheduling application, new branding assets - This week in Orchard (06/07/2021)

The new branding assets for Orchard Core are here! Check out our current post for a demo about a scheduling application, for the Auto Setup updates, and many more! Orchard Core updates New branding assets The issue was that we didn't really have concise branding guidelines or even proper branding assets. But the time has come, Orchard Core has now new branding assets! If you open up the Orchard Core Documentation, you will see the new icons and the new colors everywhere. If you click on the Resources option from the menu and select Branding from the left, you will find the updated guidelines and graphic assets for Orchard Core's branding. If you open up the admin UI of your site, you will see the new logo there too. When referring to Orchard Core, please use one of the logo variations without altering anything apart from the resolution (so don't change the colors, aspect ratio, graphics, or anything else). Bootstrap 5 for the front-end themes Orchard Core comes with some built-in front-end themes that you can use for your site. You can use a theme adapted for agency websites, a theme adapted for blogs, a landing page for a project that is under construction, and of course, the default Theme. When you use the latest preview source of Orchard Core you will notice that all of these now using Bootstrap 5, which means if you would like to use or customize them, you have the options to use the features that come from Bootstrap 5! Here is the content of the package.json file of the Blog theme. Add DistributedLock for Multi-instance AutoSetup It can happen that you have multiple deployments of Orchard Core, but you share the same database or the same Redis instance. Now you can see a new section in the documentation that explains how you can use the new optional distributed lock parameters like the LockTimeout or the LockExpiration. These help you to set the timeout in milliseconds to acquire a distributed auto-setup lock and the expiration in milliseconds of the distributed setup lock. Check implied permissions PermissionHandler should check ImpliedBy permissions. RolesPermissionsHandler doesn't have to check all user roles permissions, just Anonymous and Authenticated if applicable. RolesPermissionsHandler is scoped, so we can cache Anonymous and Authenticated permissions and not query them for each permission evaluation. Check out the default implementation of the IPermissionGrantingService interface, which evaluates if the specified PermissionRequirement is granted by provided claims. Demos Scheduling application The StatCan Orchard Core repository houses a collection of custom Orchard Core resources, modules, and themes that support various web applications and software-as-a-service (SaaS) products. Built on top of Orchard Core CMS, developers have a suite of web application features out of the box (e.g., content management, authentication, forms, themes, etc.) by customizing the selection and configuration of components. The extensibility of the framework allows new features and components to be added easily. One of the custom modules called StatCan Scheduling provides types and utilities useful for scheduling appointments. Let's see that module in action! First of all, let's run the solution and set up your site using the Vuetify platform theme recipe. The scheduling application and the Vuetify platform theme recipe are heavily built on the VueForms module that you can also find in this repository. If you haven't heard about it yet, you can open up This week in Orchard post from last year, where you can find a demo about this module. The first thing that you will see is a calendar that you can use to add appointments to it. You can add a bunch of other calendars and employees to the system. Employees can be used to say that I would like to add an appointment to this calendar for this employee. To be able to add an appointment, first, you need to add an employee to the system. It can be done using the admin UI of Orchard Core (Content -> Content Items -> New Employee). Let's say we would like to add an employee, and we assign this employee to the Default calendar. If you would like to add more than one calendar, you will find a taxonomy named Calendars. This has an AppointmentCalendar term content type. If you add a new AppointmentCalendar, you can specify its color, which will mean if you add a new appointment to this calendar, the color of the appointment will be used from here. But without further ado, let's see the front-end if you add an appointment to this calendar using our newly created employee. As you can see, we have one appointment on July 6 for the employee Gábor Domonkos. The list of employees can be seen on the right, which contains only one employee right now. You have the option to edit the given appointment or employee just by clicking on the given appointment. As we mentioned, this application is heavily built on the VueForms module that means if you navigate to Content -> Vue Forms, you will see a Vue Form content item called Create appointment, which is the component that is responsible for handling the appointment creation logic. And we are just scratching the surface of this application here. If you would like to know more about it, head to YouTube now to see it in action! News from the community Lombiq Helpful Extensions: Helpful Content Types and Widgets The Lombiq Helpful Extensions module is an Orchard Core module containing some handy extensions (e.g., filters for Projector). This time we will see the Helpful Widgets and Helpful Content types features. The Helpful Widgets adds multiple helpful widget content types. These are basic widgets that are added by built-in Orchard Core recipes though in the case of using a custom setup recipe these can be added by this feature too. Includes: ContainerWidget: Works as a container for further widgets. It has a FlowPart attached to it so it can contain additional widgets as well. HtmlWidget: Adds HTML editing and displaying capabilities using a WYSIWYG editor. LiquidWidget: Adds Liquid code editing and rendering capabilities. The Helpful Content Types includes basic content types that are added by built-in Orchard Core recipes though in case of using a custom setup recipe these can be added by this feature too. Includes: Page: Highly customizable page content type with FlowPart and AutoroutePart. The only thing you have to do is to navigate to Configuration -> Features on the admin UI and enable the Helpful Content Types - Lombiq Helpful Extensions and Helpful Widgets - Lombiq Helpful Extensions modules. And as may you guess, if you would like to add a new widget in your zone, you will see the three mentioned widgets without the need of running the given recipes that contain the definition of those widgets. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 207 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here!

Audit Trail module UI improvements, new User Event Handlers - This week in Orchard (29/06/2021)

Improving the UI of the Audit Trail module, new user event handlers, feature to lock-out users on wrong password, and many more additions to Orchard Core in our current post! Orchard Core updates New User Event Handlers You can already work with several user event handlers. Let's say you want to do something after a user is created. For example, after a user has been created, I would like to send a welcome email to that user. And from now you will find more events if you open up the IUserEventHandler interface in the OrchardCore.Users.Abstractions module. Like now you can implement the CreatingAsync method, which occurs before a user is created. Or you can use the UpadatingAsync or UpdatedAsync events too! ListPart shape names for placement The issue is that placement doesn't take into consideration the display type convention, i.e. _SummaryAdmin when placing shapes, so the convention for shape names fails, and placing a ListPart shape tries to collect all three shapes, and render them. Fixed whitespace parsing in output tags in Fluid Let's say you have the following Liquid expression which is totally a valid one: {{ "foo" | size }} But what if you write this expression in the following way {{ "foo" | size}} it would say a parse error. But from now, if you have only one expression in different lines, the parser will work as expected. For example, now you can do something like this, this will be valid: {{ "foo" |size}} Lockout on wrong password The Lockout settings are set with the settings configured in ASP.NET Identity. Those options are used to define, for example, the TimeSpan a user is locked out for when a lockout occurs or the number of failed access attempts allowed before a user is locked out. So, from now you can define the logic where you want users to be locked out and you can also set how long you want to lock out that user after how many failed access. And if you check out the documentation you will find some lines about how you can read the configuration from an external config file. Here you can say that we want to allow this feature for every new user. And if they provide a wrong username or password 5 times a row, we lock out them for the next 5 minutes. And you also have an option to unlock users from the admin UI right away. If you navigate to Security -> Users you will find an Unlock button if the given user locked himself out. As you can see in the screen below, the user with the editor user name is a locked-out one. Adding docs for the absolute_url and href Liquid filters The page about the Liquid module in the documentation is a super-useful one because here you can see the list of all the available Liquid filters that you can use in Orchard Core. And now this page got an update by adding the absolute_url and href Liquid filters to it. The absolute_url creates the full absolute URL for the given relative virtual path and the href creates a content URL for a relative virtual path. Recommended for generating URLs in every case you want to refer to a relative path. Demos Audit Trail module UI improvements The Audit Trail module provides log records for creation, deletion of any content type, and events like user events. We wrote about the Audit Trail module for Orchard Core in this This week in Orchard post, if you haven't read about it yet, start by checking out that one first. Now, we will focus on the new UI. First of all, set up your site using the Blog recipe. After, head to the admin UI of your site and enable the Audit Trail and the Users Audit Trail features under Configuration -> Features. Audit Trail: Provides a log for recording and viewing back-end changes. Users Audit Trail: The users audit trail feature allows logging of user events. Now you can set up the Audit Trail module that you can do under Configuration -> Settings -> Audit Trail. Here you will see 3 different tabs: Events, Trimming, and Content. Under the Events tab, you can select what kind of events you would like to record. For example, you can say that I want to record the fact when an attempt to login failed, but I don't care about the event when a user was disabled. Under the Trimming tab, you can say how long you want to keep your records in your database. You can say that I want to keep the records for 30 days and delete the older ones. The Content tab is about setting the types of content whose events are recorded. If you don't want to log the changes for a given content type, you can just simply untick the given one. Let's say that now we want to log the changes of every content type. We need to do some changes to be able to see records in the Audit Trail list. Let's just modify the built-in blog post. Don't forget that you still have the Audit Trail Part that you can attach to any content type. If you do that, you can optionally provide a comment about this change for the Audit Trail. Now, let's open up the Audit Trail to check out our changes. As you can see here, we published the built-in blog post two times in a row. We also published the built-in About article but for this time, we attached the Audit Trail Part too. The content of the part (the comment) can be seen under each event. Also, notice that the user with the editor username has two failed login attempts. Now, let's hit the Details button near one of the content events. The Content tab here shows you some basic data about the event: the name of the event, the timestamp of the event, the current version, and so on. You can see the JSON representation of the content item under the Diff tab. Here you can choose between two types of views: Split: the content of the previous version can be seen on the left side of the screen and the content of the selected version can be seen on the right side of the screen. You can see the previous, changed data in red and the current, modified data in green. This screen shows that the ContentItemVersionId has just changed with the ModifiedUtc and the PublishedUtc values. The reason for that is we changed the Markdown text of the blog post, by adding a new paragraph to it. Unified: the meaning of the colors is the same here, the only difference is that you can see the whole changes in one view, instead of a split one. You will see a whole new user experience when you would like to list or sort the events in the Audit Trail list. Last week we wrote about the improved search filters to the contents and users list where you could read about the syntax for the filters. And slightly the same applies here too. If you click on the funnel icon before the search box and select the Filter Syntax one, you will see a modal window that shows you the available filters. This modal describes all the registered filters that you can use with the given properties. It also shows you the current values of the given filters and a little bit of information about the syntax. And then down the bottom, you just get the current filter and the normalized version of it which describes how it's being constructed. And as always, if you would like to see more about the new UI of the Audit Trail module in action, head to YouTube for a nice and detailed recording! News from the community Piotr Szmyd Last Tuesday June 22nd 2021, our dear friend Piotr Szmyd passed away. Piotr was a respected member of our community, a steering committee member, and a passionate contributor. Everyone loved him. By creating this issue we hope you can share a story or a thought to help keep his memory alive and show his family and his friends how much he meant to us. This picture was taken in LAX on September 2012 on the way to the first Orchard Harvest conference ever. From left to right: Zoltán Lehóczky, Benedek Farkas, Piotr Szmyd and Sipke Schoorstra. May our branches merge again, Piotr! Lombiq Helpful Extensions: Flows Helpful Extensions The Lombiq Helpful Extensions module is an Orchard Core module containing some handy extensions (e.g. filters for Projector). This time we will see the Flows Helpful Extensions which adds additional styling capabilities to the OrchardCore.Flows feature by making it possible to add classes to widgets in the Flow Part editor. But how can you use the Flows Helpful Extensions feature? Let's say you have a site set up with the Agency recipe. The first thing that you need to do is to navigate to Configuration -> Features and enable the Flows Helpful Extensions - Lombiq Helpful Extensions feature. Now, it's time to edit a content item that has a FlowPart attached. The Page will be great for us now. Let's say we add a new Html widget to the FlowPart of our new page. If you click on the new cog icon, you can add custom classes to this widget and remove the grid extension classes that will be added to your widget by default. OK, but what does it mean? What's the difference? The right side of the screen below shows you the original HTML and the one on the left shows you the modified one. As you can see, the my-custom-class CSS class is there and the widget-size-* and widget-align-* classes were removed because we put a tick on the Remove grid extension classes checkbox. Removing these classes is a good idea if you are using a CSS framework that adds CSS properties to these classes but you don't want to add styling to these elements based on these classes. In this case, you don't need to overwrite these properties. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 205 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

Improving search filters to the contents list - This week in Orchard (22/06/2021)

We can write about several nice improvements this week! Adding missing deployment steps, new lines about Shortcodes in the documentation, updating the content type editor, and a demo about the search filters improvements to the contents list! Orchard Core updates Deployment steps We have several cases where we have the recipe steps but not the deployment steps. For example, now you can export the Facebook login settings but without secrets (like passwords) because we don't handle that in the recipes right now. The newly added import/export deployment steps are: FacebookLogin GoogleAnalytics Microsoft Azure AD OpenIdValidationSettings Technical name of Content Type and Display Name of Content Parts in Edit Content Type page This feature is about to show a read-only input with the technical name of the content type when you would like to edit the content type definition. With this feature, you can easily see the difference between the display name and the technical name. Of course, you can guess the display name by the technical name, but not everyone knows that. You can check it out easily. Let's just navigate to the admin UI of Orchard Core and go to Content -> Content Definition -> Content Types. Edit one of the content types, and you will see the technical name and the display name of the content type. Shortcodes docs and rename Razor helper We have the HtmlToShortcodesAsync Razor helper that you can use to render Shortcodes. This one is now renamed to ShortcodesToHtmlAsync, and the old one is marked as obsolete. And you can also find some new lines in the documentation about how to render Shortcodes via a Liquid filter or Razor helper. Check allowed file extensions when importing media You can have a list in Orchard Core that contains the file extensions that can be uploaded to the media library. If you would like to upload a PDF file to the media library and the PDF extension is not allowed, you won't be able to upload that. However, if you want to import a PDF file via recipes, you could do that because the file extension checking was missing from there. It could be a security issue but if you have rights to execute recipes, that means you have already logged in as a user who has Security Critical permissions. And one more note here: if you do _logger.LogWarning, don't forget to check is the LogLeveL.Debug enabled _logger.IsEnabled(LogLevel.Debug), otherwise, don't write a warning to the log files. Remove deprecated SHA256CryptoServiceProvider usage While running a benchmark, it started failing, the SDK throwing some warning that the CryptographyAlgorithms.CreateSHA256() is deprecated and cannot be used in .NET 6. The documentation says that now we can do SHA256.Create(), and it works for all the versions that we are targeting. Someone else from Microsoft related to benchmarking and performance mentioned this issue because they are using Orchard Core as a source for the PGO. PGO means Performance Guided Optimizations which is a way to analyze what's happening in an app to optimize the IL generated by the JIT. Demos Improving search filters to the contents list A few weeks ago, you could see a demo regarding search filters and parsers for the contents list. This demo is just about showing you the final version of the search filters that you can also try out right now if you are using the preview packages of Orchard Core! Let's see how you can use this feature that makes browsing your content items much easier! We have a site set up with the Blog recipe. The blog recipe creates an Article content type and one Article content item by default. If you want to list all of the article content items, you just need to navigate to Content -> Content Items and select Article from the filter by content type dropdown menu. As you can see, this means that the Search textbox will be populated with the type:Article expression. It means if you write, type: and the name of the content type, you can list all of the content items from the given type. If you also want to sort the items by the created date (select Recently created from the Sort dropdown menu), the sort:Created text will also appear in the Search textbox. If you click on the funnel icon before the search box and select the Filter Syntax one, you will see a modal window that shows you the available filters. This modal describes all the registered filters that you can use with the given properties. It also shows you the current values of the given filters and a little bit of information about the syntax. And then down the bottom, you just get the current filter and the normalized version of it which describes how it's being constructed. And the same applies to the Users list too (Security -> Users). Here we filtered for the Enabled users where the name contains admin, and where the Administrator role applies. Finally, we sort them by their email address. If you would like to know more about this feature don't forget to check out this recording on YouTube! News from the community Lombiq Utility Scripts: create a trusted certificate Our Utility Scripts project is open source from last year! Many scripts for Orchard Core, Orchard CMS, Azure, SqlServer development. E.g., quick Orchard Core solution init, reset/reinstall. In the following lines, we would like to show you a nice and useful script that could be a very handful one during your Orchard Core development. The CreateTrustedCertificate script creates all necessary files and imports them into the local Certificate Store so that it can be used to access localhost sites via HTTPS. If you open up that file in GitHub, you will find several comments in the script that help you to see what are the steps that are script is actually doing! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 204 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

Media search indexing, code analysis - This week in Orchard (14/06/2021)

Improving the code quality of Orchard Core by code analysis, supporting multiple translation providers, and adding a media search indexing feature to Orchard Core! Check out our post now for more! Orchard Core updates Code analysis Software is critical in all aspects of our lives. From entertainment, shopping, and dating to business-critical systems and software where human lives are at stake. And yet, security bugs are all too frequent, mainly because the process of finding vulnerabilities is manual, tedious, and repetitive, and because the expertise is not shared with other security researchers or with developers. LGTM seeks to address this situation. If you open up that site and enter Orchard Core to the search box on the top, you will see the active alerts for this repository. So, this site will go on GitHub and analyze the source of the projects. It's like a static analyzer for the code that finds potential issues, like this variable is never used, or here you are throwing an exception where you should not, and so on. We can also filter by language to see the alerts related to the C# code of the repository. Based on these issues, some fixes have been made to the source code. For example, we could remove some unused variables to make the code cleaner. Do you know that our Lombiq .NET Analyzers repository contains .NET code analyzers and code convention settings for Lombiq projects? We use these to enforce common standards across all our .NET projects, including e.g. in all of our open-source Orchard Core extensions. If you contribute to our open-source projects while using that solution, you'll be guided by these rules too. If you are interested in how to add these analyzers to your solution too, check out This week in Orchard post, but if you prefer videos, you can find a short presentation about how to use those on YouTube! Support multiple translation providers The localization manager should be able to handle multiple instances of ITranslationProvider. This feature is about supporting multiple translation providers. This way, we can create more methods for storing translations, like filesystem plus database. Right now, we have only one ITranslationProvider implementation in Orchard Core, the PoFilesTranslationProvider. This provider is part of the Localization module, which module provides the infrastructure necessary to support the PO (Portable Object) localization file format. As you can see, the LocalizationManager now injects a list of available ITranslationProvider implementations and calls the LoadTranslations method of every provider to load the translations to the CultureDictionary. Recipes Dropdown focus during setup Let's say you want to set up your Orchard Core site, or you just want to add a new tenant to it. When you move the focus from site name to recipe combo box and press Arrow Down the recipe list pops up. But when you commit your choice via Enter, focus resets to the first item on the page. Not it's fixed. It's a nice to have feature because there are people who prefer using the keyboard to navigate on the site instead of using the mouse. Serve module compile view for package reference If a module is referenced as a NuGet package e.g., OrchardCore.Application.Cms.Targets and if the NuGet package includes precompiled Views.dll, in development views are not served from the Views.dll, instead, it re-compiles all embedded cshtml resulted in a slow start in development. This code is to just ensure that it doesn't try to recompile if it finds the correct DLLs. Demos Media search indexing The idea here was to allow to search for content in files. This demo shows a feature that provides a simple implementation to index media for search. More precisely, it indexes media files related to content items, so said content items will turn up in search when one of their media files matches the search query. The following data can be indexed for each file referenced from a Media Field: Media Text The textual content of PDF files To index the textual content of the PDF files, the pull request uses the PdfPig library, which allows users to read and extract text and other content from PDF files. In addition, the library can be used to create simple PDF documents containing text and geometrical shapes. First of all, let's set up your site using the Blog recipe. This recipe constructs the Blog Post content type that has a Media Field called Banner Image. Let's say we would like to search by using the media text of the Banner Image field. To allow that, open the settings of the Banner Image (Content -> Content Definition -> Content Types -> Blog Post -> Banner Image) and put a tick in the Include this element in the index checkbox. After that, you have to do some configuration for the search fields. If you navigate to Search -> Settings -> Search, you can find the comma-separated list of fields to use for search pages. You can see the Content.ContentItem.FullText value there by default. Here we need to add the BlogPost.Image one. BlogPost is the technical name of the content type (and in this case of the content part too) and Image is the technical name of the Banner Image Media Field. Let's try out this feature quickly! Let's say we just want to edit the predefined blog post with the title Man must explore, and this is exploration at its greatest. Select the browsed image of the Banner Image field and add a media text to it. Now let's navigate to the predefined search form (https://yoursite.com/search) and try to search for the Astronaut word. This is the one that we have just added as the media text to our blog post. Astronaut is not a word that would actually show up anywhere in the body. As you can see, our blog post has just appeared as a result of the search. If you attach a PDF file to the Banner Image media field and try to search for a word or a phrase that is inside the PDF file, the query will return that content item too. This feature is still under development by Zoltán Lehóczky from Lombiq and as we mentioned you can find the PR containing the code here. If you would like to know more about it, don't forget to check out the following recording on YouTube! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 203 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

GrahQL Queries queries, Negative role condition evaluator - This week in Orchard (07/06/2021)

We start this week by showing the ability to export templates as files, the negative role condition evaluator, and the brand new alternates for widget parts and for dynamic parts with great examples in the documentation. After, we will see a great demo about using templated GraphQL queries with Liquid. Check out our post for more! Orchard Core updates Add ability to export templates as files The idea here is in the exported ZIP file, the templates are now files instead of being embedded in the JSON recipe. Let's check it out quickly! Let's say you have the Templates module enabled (the Templates module provides a way to write custom shape templates from the admin) and have a defined template. If you set up your site using the Agency recipe, you will have one template, called Content__LandingPage, which is a template for the Landing Page content type, and the homepage of that installation is a Landing Page content item. Now, head to Configuration -> Import/Export and create a new Deployment Plan under the Deployment Plans option. Let's name the plan as Templates and add one Deployment Step to it, the All Templates one. Here you will see a new option: Export templates as files. Let's just put a tick in this checkbox to see what will happen. Now we have only one thing left to do, to execute the deployment plan. Let's just download the deployment plan locally and check the content of the Templates.zip file. Here you will see a Recipe.json file and a Templates folder. The Recipe.json file contains the Templates step with our only one Content__LandingPage template, and the content of that template can be found in the Content-LandingPage.liquid file in the Templates folder. Negative Role Condition Evaluator The way a role condition with a negative operator is evaluated right now doesn't take multiple roles into account. If we have 2 users: -- roleA roleB UserA X UserB X X The evaluator uses .Any() when evaluating the value against every role of the user. If we pick the operator "Equals" with the value "roleB", it will only be true for UserB, which has roleB. If we were now to just change the operator to "NotEquals" logically, it should be the opposite result of "Equals" but since the value gets compare against every role and roleA != roleB it will return true as well. .Any() (Current) Operator Value UserA UserB Equals roleB false true Not Equals roleB true true Contains roleB false true Not Contains roleB true true Using .All() with the negative operators which would give opposite results as intended. .All() Operator Value UserA UserB Equals roleB false true Not Equals roleB true false Contains roleB false true Not Contains roleB true false We have many negate operators, like StringNotContainsOperator, StringNotEndsWithOperator, StringNotStartsWithOperator, StringNotStartsWithOperator. Now, if you use them, the code execution will return with using the .All() instead of using the .Any(). If you don't know what are the rules and how to use them, check out the demo about the Rules module in this post! Validate content type and part names There was an unhandled exception during content item creation if you have a part named like property on ContentItem. The reason was that we have some reserved names that you cannot use when you are naming your content parts or content types. The _reservedNames HashSet here contains the names, that you cannot use. Use ZStringWriter ZString is a library that provides StringBuilder and StringWriter with zero allocation, meaning it's allocating an array on the stack for small buffers, instead of creating new StringBuilders and StringWriters every time. All ZString methods only allocate the final string. Also, ZString has enabled to access the inner buffer, so if the output target has stringless API, you can achieve completely zero allocation. Now we can use the new ZStringWriter instead of the existing StringWriter one. Alternates for Widget Parts This change contains several new alternates for widget parts and dynamic parts. And the documentation has also been updated with the new alternates. And when we are saying that the documentation has been updated, we mean that it's really got a huge update with many examples, like Display mode with Part Type and Shape without Display type Examples, Display mode with Part Type and Shape with Display type Examples, Display mode with Part Name and Custom Shape with Display type Examples and many more. Demos GraphQL Queries queries Let's meet with the new GraphQL Query type that basically allows you to use a GraphQL query in the admin interface and Liquid. It's using the same principle as the SQL query or the Lucene query. For example, let's say we have a GraphQL query created called ContactRequests, which is just about getting the Contact Request content items from the site. This query returns the contentItemID, the createdUtc, and the display text values of the Contact Request content items. But by using this experimental feature, you have the availability to use a templated GraphQL with Liquid. What do we mean? Well, first let's find the new Run GraphQL Query under Search -> Queries. Here let's add a template that contains Liquid code. By using Liquid, you can add output parameters to your query. In this case, we would like to get the email and the message fields too of the Content Request content items by using parameters. As you can see, we used the contactRequestEmail parameter to get the email and the contactRequestMessage parameter to get the message. If you open up the StatCan Orchard Core repository, you will find a collection of custom Orchard Core resources, modules, and themes that support various web applications and software-as-a-service (SaaS) products. One of the modules here is the VueForms module, which provides a form ContentType that simplifies using VueJs forms in the frontend. We had a demo about that one too, way back in 2020. If you don't remember about that, you can check out that in this post! And as always, if you want to know more about this feature, don't forget to check out the following recording on YouTube! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 203 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here!

Admin Layers, move admin branding to a distinct shape - This week in Orchard (31/05/2021)

A new demo about Admin Layers, several performance improvements, and a new AdminBranding shape is waiting for you in our upcoming post! Oh, and have we mentioned that Lombiq is now more than 8 years old? :) Orchard Core updates Move admin branding to a distinct shape Now you will find a brand new AdminBranding shape in the default admin theme of Orchard Core that is about containing the favicon, and the default, clickable Orchard Core logo that redirects the user to the home page of the admin UI (the admin dashboard). And now, because this whole stuff is a new shape, you can easily customize this one too! Check out the updated documentation to read some words about it! Fix drop widget to empty zone Someone reported an issue that it's not possible to drag and drop widgets to an empty zone. Now, this has been fixed. Remove some async-await It's not a recommendation anymore to remove async/await when it can be removed. In this case here the Task from _session.Query can be returned directly, it doesn't have to be awaited. There is a benefit in terms of allocations but at the same time if there is an exception you lose where it's coming from. And the impact in terms of perf is minimal. So, it's not a recommendation to do it every time. Adding spatial features to content (Lucene indexed) You could see a demo a few weeks ago about adding spatial features to content. This module provides a GeoPointField, which can be used to give a geographic position to content. And this has been merged to the dev branch of Orchard Core with nice detailed documentation also! Don't forget to check out the docs to read about Terms specifications, Geo Bounding Box, Geo Distance, and many more! Reduce string allocations in MediaTokenService and use pooled StringBuilder instances with StringWriter Now the code is using StringBuilder from the StringBuilderPool instead of using String.Concat(), which is about allocating one buffer. There are other improvements with the queryStringTokenKey, which is not recreating a new string every time, just using the existing one. StringWriter will create a StringBuilder by using the StringBuilderPool and passing that to the StringWriter. It's not creating a new one, it's just reusing the existing one. Demos Admin Layers People want to change shapes or styles for various things on the admin UI without having a custom admin theme. For example, currently, it is not possible to change the admin panel's logo and icon without a custom theme (set the base theme to Admin). The new Admin Layers feature is very similar to the Admin Templates one. This new one is about working with the layers of the admin theme, which means you can put different kinds of widgets to the zones of the admin theme using different kinds of layers rules. Sounds familiar? Yeah, that's the goal of this one! Let's say you set up your site using the Blog recipe. After go to the Configuration -> Settings -> Features and find the Admin Layers one which enables admin users to render widgets across pages of the admin based on conditions. Now, the first thing to do is to set up the available zones for widgets as you would do that in the case of the front-end widgets as well. You can do that under Design -> Settings -> Admin Zones. Let's say we would like to work with the HeadMeta, Footer, Header, and NavbarTop zones for now. And let's add some layers too! If you navigate to Design -> Admin Widgets, you could see a very-very familiar UI to manage zones and layers. Here we have just added a simple layer called Always that has one boolean condition rule, which is True. Meaning the widgets on this layer will always be rendered. Now, let's do some testing! Let's say we add a simple Raw Html widget to the NavbarTop zone that is just about containing some bold text. After we will create a new Liquid Widget and render it in the HeadMeta zone. The Liquid Widget is just about containing some styling for the theme: {% styleblock at:"Head"%} body { background-color: gray !important; }{% endstyleblock %} Now we have created two widgets that we have displayed on the Always layer of the admin theme. Let's see how our theme looks like! First, notice the Some text in the NavbarTop zone near the moon icon. This is the Raw HTML widget in the NavbarTop zone. And the new background color is coming from our Liquid Widget. If you would like to know more about this feature, don't forget to check out the following recording on YouTube! News from the community Lombiq is 8 years old! May 21, 2021, is the 8th anniversary of founding Lombiq! On this special occasion, we have gathered 8 important factors of our company's life. We are glad that we took these steps at that time otherwise we might not be able to celebrate with our strong community here today. Check out our post to see which important factors we gathered together! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 202 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

Client-side validation of the form elements, fix content item shape usage in Liquid - This week in Orchard (26/05/2021)

Documentation updates, fixes for the content item shape when calling it using Liquid, a new extension method for the IContentManager, and a demo about client-side validation of the form elements. These are the main topics for our current blog post! Orchard Core updates Adding docs on the Recipes recipe step A recipe is a JSON file used to execute different import and configuration steps. You can add it in a Recipes folder with a name like this {RecipeName}.recipe.json, and it will be available in the Configuration > Recipes admin page. A recipe can execute multiple steps. In order to create a new Recipe step, you need to implement the IRecipeStepHandler interface and the ExecuteAsync method: public async Task ExecuteAsync(RecipeExecutionContext context). This page of the documentation mentions the available recipe steps, but the Recipes Step is missing from the list. Now you can read about what is the Recipes Step exactly and how you can add them to your recipe file! Fix content item shape usage in Liquid There was some confusion about the difference between alias and handle when using the content item shape in Liquid. The handle is the way you can reference content items with logical names and not physical IDs. In this case, you can reference a content item by its alias, which is the test here, or by its slug, which can be blogpost1. But if you type the alias here, it will still work because some code falls back to that. The Detail display type is the default one, so you don't have to specify it in the helper. But rendering the given display type here didn't work because there was an issue in the ShapeTag.cs code. As you can see, there was an argument.Name.ToPascalCaseDash() call for each argument. But the right method to use here is the ToPascalCaseUnderscore(), which takes display_type and converts it to DisplayType. Load items in Admin List Now you can find tons of new extension methods on the IContentManager to call LoadAsync. When you call this new ListAsync extension method, it will call the LoadAsync too, which will invoke the LoadingAsync and LoadedAsync events to acquire state or at least establish lazy loading callbacks. Don't allocate for page output writing in LiquidViewTemplate When we have the RazorPage class in ASP.NET Core, it has an Output property, which is about getting the TextWriter that the page is writing output to. We use that to render out our Liquid Templates. But when we do that, the output object is actually a buffered writer that will take whatever we write to it and buffer it and write it again to the actual results at some point. But what happens here is Liquid will write every snippet of data, every fragment to this writer, which will be duplicated in memory because it doesn't know that it can reuse it or who owns the data. Knowing that if we look at the implementation of ASP.NET, there is a class named ViewBufferTextWriter, that has a custom Write(IHtmlContent) implementation that would check if the object we pass is an HTML content. And if it's HTML content, then it won't try to allocate anything, it will just keep a reference to it. So, by doing page.Output.Write(content) it's now invoking ViewBufferTextWriter.Write(IHtmlContent) which doesn't allocate anything. And then, when the IHtmlContent is used, it should write directly to the response buffer. Demos Client-side validation of the form elements This demo is about form element validation. There is an in-progress pull request by Spike where you can find the complete form validation implementation using the Validator.js library, which is a library of string validators and sanitizers. We can use this to have validation for form elements with one rule both on the client-side and on the server-side in a user-configurable way. We set up our site using the Blog recipe and created a Page content item that contains a Form in its FlowPart and posts its input elements to a Workflow. The input elements are just about to demonstrate some validation rules. If you add a new Input, you can see some new fields, like the Validation Type, the Validation Options, and the Validation Message. As you will see from the Readme.md file of the Forms module, there is a high variety of functions that are implemented and can be used as the Validation Type. Now let's try out the Contains Validation Type! Let's say we have a rule that the textbox should contain the 'think' word. To do that, we simply write the 'think' word in the Validation Options textbox and also added a nice error message. But as you can see, there are lot more options that you can choose from to validate the inputs of your form, which works the same way. And here comes the workflow that we are using to submit the form. The FormRequest one is just a simple HTTP Request event followed by the Validate Form one, which checks whether the submitted form contains any validation errors. And if there were no validation errors, we redirect the user to the /Success URL, otherwise, the user will be navigated to the /Error URL. But that's not all of it! Head to YouTube now to check out the recording about this very useful upcoming feature! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 199 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

YesSql 3, Liquid Widget guide - This week in Orchard (17/05/2021)

YesSql 3 is here! Check out our current post to see what's new in YesSql, but first, read the new Liquid Widget guide and get to know why do the community needed to delete the Liquid Page and the Liquid Widget from the Blog and Agency recipes! Orchard Core updates Remove liquid type from recipes This is from a security report that if you have access to the admin, you can use and write in the LiquidPart. By using LiquidPart you can write HTML and JavaScript. It sounds obvious, but some sites don't expect users to be able to edit JavaScript on their pages, and it might have an issue. Because if you can write JavaScript, you can write XSS. The solution here is to remove the Liquid Page content type and Liquid Widget from the Blog and the Agency recipe. But the part is still there, and you can use it. And the Edit content types permission is marked as Security Critical. Meaning that, if you allow this permission to users, you let them be able to also use the LiquidPart and create some custom types that are about to render JavaScript in the frontend. Liquid widget guide As we mentioned previously, the Liquid Widgets from the default recipes were just removed. But that content type served as a very good example of how you can work with Liquid in Orchard Core. To have an example for working with Liquid, you will now find a new guide in the documentation about how to build a new Liquid Widget. Sometimes not having a feature but documenting how to use something is better than having a feature and no documentation about it. Did you know that our Helpful Extensions module for Orchard Core contains a Liquid Widget too, that adds Liquid code editing and rendering capabilities? Check out that repository for more goodies like the content definition code generation or the flows helpful extensions and many more! Use nameof for action name whenever it's possible Any controller action name that doesn't change can be called by using the nameof expression of C#. Now you won't break anything if you change the name of a method during some refactoring. Contents GetAsync: Recall published items Calls to IContentManager.GetAsync(string contentItemId, VersionOptions options) use IContentManagerSession.RecallPublishedItemId() to retrieve an already loaded content item if the request is to get a published item. The same could be used in GetAsync(IEnumerable<string> contentItemIds, bool latest = false) (i.e., the overload accepting multiple IDs). And the fix is here! When you do some loads with the content manager and if the content items are already have been loaded previously in the same request, there is no query that needs to be issued or just for the items that are missing. Demos YesSql 3 In the previous version of YesSql, every session created a new transaction automatically by default. Every session means even if your session is only doing reads. But when you are doing reads, you don't need a transaction because every read will be using the same transaction resolution. When you start a session in YesSql 3 and it's just about doing reads (like SELECTs) then it won't create a transaction. But the first time when you do a change on an object, the transaction will be created automatically (like when you would like to update a content item). Now it lazily creates a transaction if there are UPDATE, DELETE or INSERT statements. The second change is that if you really want to decide when the transaction should be created and not to wait for it to be automatically created. You can now call BeginTransaction and that will create a transaction or return the existing one if one is still open. And then there is another property (CurrentTransaction) that gives you either the existing transaction or NULL if there is no transaction. Everything has been renamed from CommitAsync to SaveChangesAsync. It's like in Entity Framework and now it's more obvious to know what it does (saves the changes). And what it means is that at that point if there is a transaction it will be committed and then released. If there is no transaction, it's just do nothing. And there is still the AutoFlush, meaning if you do some updates and then do a query to get some data, it will flush the changes from the database without committing a transaction, but your next request will be able to read the values that aren't in the database. Something that you can't do with YesSql before is let's say you start creating a session and there is an exception in the middle. If you didn't do a try-catch, and call CANCEL on the catch, it would commit the transaction because disposing of the session was committing the changes. In ASP.NET we don't have this issue because there is a rule that catches any exception that happens anywhere in the pipeline. But in some other apps, if you forget a try-catch, it would commit the changes even if it didn't go over the full list of commands that you want to execute. That was a big issue in YesSql. So, now that's actually changed. Meaning that if you don't call SaveChangesAsync now, it won't save anything. You have to call SaveChangesAsync at some point to commit the transaction. And if you disposing the session before calling SaveChangesAsync, it will cancel the transaction if it exists and closes the connection. So, SaveChangesAsync is now mandatory to mimic the EF behavior. So, if you have modules that use the session, you need now to call SaveChangesAsync, otherwise, nothing will be saved. But you should not have any module that calls SaveChangesAsync. And that's not all! If you would like to know every new feature and performance improvement included in YesSql 3, don't forget to check out the following recording on YouTube! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 199 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post is published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!