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

Copilot Integration, Last call: Speaker application for Orchard Harvest 2026 - This week in Orchard (01/05/2026)

This week, Mike Alhayek shows how to use Copilot directly inside Orchard Core!

But before that, check out some code where you can see that, starting now, Orchard supports static data migration methods, and suppressions are no longer required for migration steps that don't use instance state.

Welcome the first contribution from Jack Liu, who made the pagination of the List Part configurable to decide whether to show a full pager with page numbers or just the arrows to navigate to the previous and next pages.

Do you know that since 2013, we've been working with Óbuda University in a hands-on way to teach web development? If you are interested in our Orchard Core courses at the university, check out our post on our site!

As we mentioned, we started publishing last year's Harvest recordings to YouTube. Check them out for some inspiration, and don't forget to apply to be a speaker for this year's Harvest by the 5th of May, midnight, anywhere on Earth!

Ready to explore? Let's dive in!

Latest tutorials

Featured tags

AI
IIS
MCP
API
SMS
SEO
All tags >

Use shape when rendering HTTP errors to allow customization from the UI, Git-hg Mirror is running on Orchard Core - This week in Orchard (01/12/2023)

Use shape when rendering HTTP errors to allow customization from the UI, add extensions for IDisplayManager, and a case study about migrating Git-hg Mirror to Orchard Core are the topics for this week. Let's check them out in detail! Orchard Core updates Use shape when rendering HTTP errors to allow customization from the UI The idea here is that you might want to customize the error pages without having to create a theme. The way to do that is to create shapes. The reason you had to create a theme is these pages were used to be views, so you couldn't override them dynamically. Now (because they are shapes), you can create them in the admin UI and the theme. So, if you want to be able to override the error pages using the Templates feature, now you can do that. For example, if you want to customize the 404 page using Liquid templates, enable the Templates feature, add a template called HttpError__NotFound, and design it how you want it. In this case, we selected the Templates option under Design (enabled the Templates feature first) from the admin menu and clicked on the Add Template button. Here we named our template HttpError__NotFound and provided a sample content. After we clicked Save. The only thing left is to enter a random URL to check out the content of our custom 404 page. You can read more about this enhancement on the newly created Diagnostics page in the documentation. It's a breaking change because if you have customization before, now you have to rename the views or relocate them. This was also documented in the notes of the next Orchard Core release. Add extensions for IDisplayManager This introduces new extension methods for the IDisplayManager that displays a shape using TModel, meaning you don't have to do a new Navbar() for example, as you can see on the screen. The release notes of the next Orchard Core release have also been updated with these changes mentioning how you can add the Navbar shape into your front-end theme utilizing the new extensions. News from the community Case study: Git-hg Mirror is running on Orchard Core Our Git-hg Mirror service can sync between Git and Mercurial repositories, as well as two Git repos. Originally built on Orchard 1, now it runs on Orchard Core! Check out our case study here about the migration! We are happy with the results and the additions to our open-source modules, and stay tuned, as we keep the migrations rolling. If you're considering migrating your Orchard 1 website to Orchard Core, this is an excellent time. Should you have any questions or encounter challenges, don't hesitate to reach out to us. We're always ready to bring our expertise to your unique project needs. Get in touch with us today, and let's start making your Orchard Core website even better! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 488 subscribers! We have started this newsletter to inform the community around Orchard of 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 would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news about Orchard and the details of the topics above, don't forget to check out the recording of this Orchard meeting!

Introduce a new Navbar shape, Stimata Hotel is using Orchard Core - This week in Orchard (10/11/2023)

Introducing a new Navbar shape, centrally defining media resources, and the brand-new Orchard Core site of Stimata Hotel! Let's get right into the news! Orchard Core updates Introduce a new Navbar shape In the Admin theme, multiple shapes were injected in the Navbar space. We had a zone, that was called NavbarTop, we were injecting the user menu, and then we were injecting a shape for the links. We were creating three shapes, and instead, we now have a Navbar shape, which you can utilize in the Admin theme, in the Theme, and in your own theme. It allows you to utilize drivers to be able to add line items inside that Navbar shape. That makes things more dynamic. Like injecting a theme toggler, the icon that navigates you to the front-end site, the culture picker, etc., can be done by using the driver. You can read more about it by visiting the docs, and the change logs of the upcoming Orchard Core version are also updated to tell you some more details about it, for example, how you can add the Navbar shape into your own front-end theme and back-end theme. Centrally define media resources This change is about centrally defining media resources to avoid scattered file references. The script and the CSS files needed for the Media-related fields and parts (Html Body Part, Html Field, Markdown Body Part) were always injected in a way where we defined the source and the dependencies of the required resources. By adding these resources to the ResourceDefinition, we can easily inject them just by using their name. News from the community A new website using Orchard Core: Stimata Hotel Stimata Hotel is nestled in Flampouria, a charming coastal nook on the western side of Kythnos, captivating with its sandy beach and the mesmerizing sunset over the deep blue sea. Check out their brand-new, amazing-looking Orchard Core site here! If you are interested in more websites using Orchard and Orchard Core, don't forget to visit Show Orchard. Show Orchard is a website for showing representative Orchard CMS (and now Orchard Core) websites all around the internet. Ryan Drew Burnett started it, but since he doesn't work with Orchard anymore, as announced earlier, it is now maintained by our team at Lombiq Technologies. Oh, and in case you haven't read our previous post yet, Show Orchard is now running on Orchard Core! Here's the case study about how we migrated it from Orchard 1! If you're considering migrating your Orchard 1 website to DotNest Core, this is an excellent time. Should you have any questions or encounter challenges, don't hesitate to reach out to us. We're always ready to bring our expertise to your unique project needs. Get in touch with us today, and let's start making your Orchard Core website even better! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 484 subscribers! We have started this newsletter to inform the community around Orchard of 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 would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news about Orchard and the details of the topics above, don't forget to check out the recording of this Orchard meeting!

Add media file settings for allowed file types, Lombiq’s Journey with WTW’s Client Portal - This week in Orchard (29/09/2023)

Make UserMenu and LoginMenu extensible to using drivers, add media file settings for allowed file types, and a blog post about Lombiq’s Journey with WTW’s Client Portal! Let's see the details in our post! Orchard Core updates Make UserMenu and LoginMenu extensible to using drivers Currently, there is no easy way to extend or inject items in UserMenu and LoginMenu. This is because all items in there are hard coded. If you remember, a few weeks ago we talked about the User Display Name and the User Avatar features, and in the recording, Mike Alhayek showed how difficult it is to change the UserMenu or LoginMenu shapes. The suggestion was to make these shapes extensible. From now on, to inject new menu items in either the LoginMenu or UserMenu you can implement and register an implementation of DisplayDriver<UserMenu>. The Detail display type is used to create the front-end menu, whereas the DetailAdmin is used to create the admin menu. Here you can see screenshots from TheTheme theme and from TheAdmin theme. As you can see, every menu item has its own shape which makes extending the items of these menus way more flexible. Add media file settings for allowed file types Currently, when using Media Field, there is no way to restrict which file types can be used. Any extension that is uploaded can be selected. This works great for the most part. But what if you want to allow specific types? For example, creating a slide show of some sort. You should not be able to select non-image files for a slide show. Having a way to specify image extensions will help in this case. And here comes the new settings! Here, you can see that we have a content type called Slide Show Item. This content type has a Media Field attached, called Pictures. If you edit the Pictures Media field, you have a way to set the allowed media types (image types for our case) by using the image types checkbox which helps you to select all the file extensions with the "image" type. With the help of this friendly UI, you can easily say that you only allow users to upload images using the Pictures Media Field. Note the list of the extensions here comes from existing MediaOptions. News from the community Lombiq’s Journey with WTW’s Client Portal WTW is a multinational company providing services, such as insurance brokerage, risk management, and human resources consulting. Recently we implemented a specialized Orchard Core Client Portal for them. It was an exciting project, and we delivered it on time. While the final steps on the rest of the architecture are being completed, the whole portal is gradually being rolled out to users during the summer of 2023. If you are interested in the details, check out this case study for more! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 499 subscribers! We have started this newsletter to inform the community around Orchard of 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 would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news about Orchard and the details of the topics above, don't forget to check out the recording of this Orchard meeting!

Orchard Harvest Program, Tenant Clusters - This week in Orchard (19/05/2023)

Allow displaying an icon for Custom Settings, add Admin Culture Picker docs, demo about Tenant Clusters, and most importantly, the program of the Orchard Harvest is now available! Let's get started! Orchard Core updates Allow displaying an icon for Custom Settings You can create a setting using Custom Settings and set the item icon in the menu that came with it. It wasn't really possible before this change because the .Id(type.Name.HtmlClassify()) and .AddClass(type.Name.HtmlClassify()) weren't applied in the AdminMenu of the CustomSettings module meaning it was not possible to override this menu item with a shape named NavigationItemText-NAME_OF_SETTINGS.Id. From now on, the CustomSettings module allows us to set the icon of the newly added menu item. Add Admin Culture Picker docs A few weeks ago, we mentioned that you have the option to add an admin culture picker for the admin site and have a dropdown in the admin panel header to switch languages. And of course, when adding new features to Orchard Core, we always keep in mind the flexibility and the reusability that Orchard Core can provide to the developers. Meaning, you can override and customize the shapes which are responsible to display the admin culture picker. Now we have some lines in the documentation about the two shapes that are responsible for displaying the admin culture. Demos Tenant Clusters This demo is about a work-in-progress feature for Orchard Core that distributes requests across tenant clusters using Microsoft Yarp.ReverseProxy. If you check out the following recording, you can easily get up to speed with the current state of this upcoming feature. Here we want to highlight some of the more exciting parts of this addition: We first use the Yarp Configuration to define Routes and Clusters with many options. Each Route is tied to a Cluster composed of Destination(s) on which load balancing can be applied. We only need one catch-all RouteTemplate and multiple Clusters on which we can configure a custom SlotRange[min, max] property (up to 16384 slots). Each tenant has a unique slot hash, so a unique Slot then belongs to the Cluster having the slot in its SlotRange. The Cluster can have multiple Destination(s). We could have used a Cluster having Nodes, but we follow the Yarp Config having a Clusters list of Cluster type. The same application can run as a proxy or behind it (we check the headers), the advantage with our distributed services is when as a proxy we are still aware of all tenant's data. So, on a request, we can use the same RunningShellTable to know the tenant, then select the right Cluster based on the tenant slot hash (in a custom middleware), and let Yarp selects one of its Destination(s). To compute a tenant slot hash, we use the CRC-16/XMODEM algorithm (same as Redis uses for clustering keys) applied on the new TenantId property, which allows us to automatically spread out new tenants on the slots and then on the configured Clusters. This knowing that the CRC-16 is fast to compute and always returns the same number for the same TenantId, so a tenant stays on the same Cluster. News from the community Orchard Harvest Online Program As many of you know, we have been working hard over the past months to organize the next Orchard Harvest in Las Vegas after the last Harvest in 2017. Unfortunately, based on the current economic situation and personal feedback, Las Vegas won’t work this year. Not to mention that unfortunately Microsoft Build, announced after we decided on our dates, also falls in line with the original dates we chose. So, a date change was also necessary. However, we did not want to let go of this opportunity to meet completely. Therefore, we are pleased to inform you that we will be holding our first online Orchard Harvest starting on the 31st of May at 13:00 UTC. You can start your registration for the event right now. And in the meantime, the program of the conference is available on the official site of Orchard Core! Please welcome the below selection of awesome talks by community members! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 458 subscribers! We have started this newsletter to inform the community around Orchard of 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 would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news about Orchard and the details of the topics above, don't forget to check out the recording of this Orchard meeting!

Add fallback alternate when a custom stereotype is used, tenant removing - This week in Orchard (16/09/2022)

Add fallback alternate when a custom stereotype is used, validate database connection before allowing a tenant to be added or set up, remove localization workaround in Data Annotation Attributes, and a demo about the upcoming tenant removing feature! Check out our post for the details! Orchard Core updates Add fallback alternate when a custom stereotype is used The idea here is that when you create a stereotype, before this change, you had to create templates for this stereotype if you intended to display or edit items of this stereotype. And now, there is a fallback shape for stereotypes such that if you don't create custom templates, it will use a standard, default template that is valid for any stereotype. How it works is just to let's use the Content shapes for anything when we don't have a custom template. It prevents showing error messages when you create a stereotype and try to create a content item from this stereotype. And you can test this one easily. Just navigate to the admin UI of Orchard Core and head to Content -> Content Definition -> Content Types, where you can find the Create new type button to define your new content type. Add a name to it and hit Create. We will not add any Parts to it right now. Set the Stereotype to Cat and hit Save. Now we can create a new Animal content item by clicking on the New button and selecting Animal under Content -> Content Items. And as you can see, Orchard Core now renders the default Content_Edit template as a fallback instead of throwing an exception. Validate database connection before allowing a tenant to be added or setup When adding a new tenant, we allow the user to set a prefix to the tables to enable reusing the same database for multiple tenets. However, we don't validate that the prefix isn't already used first. The problem with this is that it throws an exception. Let's say we have a tenant with a URL prefix test and we selected the SQLite database. Now let's create another tenant using the same URL Prefix and database preset. As you can see, now we have a validation error. But we also have validation for connection strings as well. Let's say we would like to use SQL Server and provide a connection string that is invalid. In this case, you will face an error like "The provided connection string is invalid or server is unreachable". Remove localization workaround in Data Annotation Attributes Two years ago, when Hisham Bin Ateya started the support data annotations PO localization PR, there was a long discussion to support localization in data annotations. Back in the day, Antoine Griffard did a workaround to achieve the goal by using IValidatableObject, and now it's time to remove this workaround and use the new way of doing this. This means we can remove the need of implementing the IValidatableObject from several ViewModel. And from now, on you can use some attributes which help you print localized error messages. And now there is an attribute for email validation and URL validation as well. Let's see an example quickly! As you can see here, the RegisterViewModel implemented the IValidatableObject to be able to validate the properties inside the class. Now, instead of using the IValidatableObject, we can add attributes to these properties, and here comes the new EmailAddress attribute as well. As you can see from the screen, the new implementation of the ValidationAttribute can be used to validate your model by returning a localizable error message. Demos Tenant Removing The option to be able to remove tenants is a long-requested feature, and for now, we are very close to shipping this feature, thanks to Jean-Thierry Kéchichian. Let's see how it will work! For this demo, we will navigate to GitHub and checkout this branch. Now, let's add some tenants to be able to try out this feature. As you can see, we have added 3 tenants. The Agency and the Blog ones are tenants that we have already set up, but the tenant called test is waiting for setup. Here you can see that we have the Sites folder under App_Data where each of the tenants has its own folder containing the Media files for example. And now we also have a wwwroot folder under OrchardCore.Cms.Web, which contains a folder per tenant like in the previous case. This means now each tenant can manage their own cached files under wwwroot. When we remove a tenant, the logic will also remove the folder of the tenant under the wwwroot and the Sites folders. And now it's time to delete a tenant! To be able to delete a tenant, we should disable it first, which means it will be not served, and we will be able to compose an internal ShellContext with all the features that the tenant has, even if it is installed or not. You can also remove multiple tenants by using bulk actions. And this is just the surface, there are still some things to do. If you would like to see the current state of this feature and do a deep dive under the hood, check out this recording on YouTube! This feature is sponsored by Lombiq. News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 347 subscribers! We have started this newsletter to inform the community around Orchard of 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 Orchard meeting!

Implementing Zone shape alternates, Lombiq UIKit for Orchard Core - This week in Orchard (25/08/2021)

We can write about several nice improvements this week! Adding missing deployment steps, new strongly typed example with update endpoint in the documentation, implementing Zone shape alternates, and many more! Orchard Core updates Implementing Zone shape alternates This feature is about adding Zone shape alternates like in Orchard 1. The Zone__[ZoneName] template is called when displaying a Layout zone. Which zones are available depends on the current theme. And now you can find a new section in the documentation of Orchard Core about what are the available properties of the Zone shape and how to display the content of a given zone using Liquid and Razor. Allow file attachments for deployment steps Let's say you need to create a custom deployment step that accepts an Excel file as an input with data to use for creating a custom deployment step. But the form posted does not accept attached files. The issue was that the OrchardCore.Deployment/Views/Step/Edit.cshtml file has no enctype="multipart/form-data" attribute. Expanded strongly typed example with update endpoint The Content Types page of the Orchard Core documentation is about showing you how to use migrations to create your new content type, how to change the metadata of your content type, or how to add content parts or content fields to your type. Now there is a new sample that shows how to update your strongly typed content item using an API in this case. The UpdateProductPriceAsync is just about getting the Product content item by an Id and updating the value of the Price Numeric Field of it, which can be found on the ProductPart. Add site settings deployment for Content Audit Trail Settings and Google features When you navigate to Configuration -> Features and enable the Audit Trail module, you will have a feature that provides a log for recording and viewing back-end changes. If you navigate to Configuration -> Settings -> Audit Trail and click on the Content tab, you will see a list that contains all of the content types of your installation. Here you can select the types of content whose events are recorded. And now you can export these settings using a deployment plan! To do that, just create a new deployment plan (Configuration -> Import/Export -> Deployment Plans) and add a new deployment step to it. You just need to find the Content Audit Trail settings one that exports the content audit trail settings. If you execute your deployment plan, you will see that the recipe file contains the list of the allowed content types. And the same goes for the Google Analytics and Google Tag Manager modules. If you enable those, you will find some settings under the same Configuration -> Settings option called Google Analytics and Google Tag Manager. Now you just need to add the Google Analytics Settings and Google Tag Manager Settings deployment steps to your plan, and after you execute that, you will get the following recipe file. Demos Lombiq UIKit for Orchard Core The Lombiq UIKit for Orchard Core module contains reusable shapes like text editors, custom-style checkboxes, dropdown editors, and in the future potentially more complex editors. Add the module to your solution and enable the Lombiq UI Kit - Showcase page feature if you want to check out the currently available shapes. You can see them under ~/UIKitShowcase after the feature is enabled. The example code for using these shapes can be seen in Views/Showcase/Showcase.cshtml. This module contains only those stylings which are needed for these shapes to work. During one of our client projects, we needed to standardize UI elements both on the front end and the admin area. Like text fields, drop-downs, and so on. Once you go beyond the very basics with styling and functionality this comes a bit more complex. Centralizing things is a good option in this case, and while we are doing that let's have an open-source module about it. And we have already added this module to our Open-Source Orchard Core Extensions solution! The only thing you need to do is to clone this repository and set up your Orchard Core site with any recipe you want. After head to the admin UI of Orchard Core and enable the Lombiq UI Kit - Showcase page and Lombiq UI Kit modules. Now you just need to navigate to the https://localhost:44335/UIKitShowcase URL, which showcases all the elements that are built-in into the module. But how can you use these? Especially they are just simple tag helpers. If you open the mentioned Showcase.cshtml in the Lombiq.UIKit module, you will see the content of the showcase page. Here you can see we have the editor tag helper that accepts several properties like the type, labelPosition, iconClasses, placeholder, and so on. By just providing these you can have nice, standardized UI elements that can be also used in Liquid as well. If you would like to know more about this feature don't forget to check out this recording on YouTube! News from the community DotNest Core DotNest Core is a complete redevelopment of the DotNest platform, all on the latest version of Orchard Core. We've been running it with a couple of select few customers for a while now, and it's time to open it up a bit more. While you can't yet simply create an Orchard Core-based DotNest site, you can sign up for our limited beta here. You'll soon be able to get a fully functional, reliably hosted Orchard Core site on DotNest where you can build your personal website or something to showcase your Orchard skills with. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 219 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!

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!

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!

Reimplement batching in YesSql, Azure Application Insights module - This week in Orchard (26/02/2021)

Refactoring the Content zone, reimplement batching in YesSql, hiding Setup recipes, adding more indexes to index tables, Azure Application Insights module and a lot more is waiting just for you in this post! Orchard Core updates Do not display Setup recipes in the admin UI You can easily list all of the existing recipes of your site under Configuration -> Recipes. If you create a recipe, like myrecipe.recipe.json, and put it in a Recipes folder of one of your modules, that recipe will be listed on this page. Let's add a simple one and check out the content of that page. You can see that our recipe with the display name My Recipe is on the list but wait! What happened with the other recipes? We have several other built-in recipes like the Blog, the Agency, and so on. Where are they? From now the logic in the Index method of the AdminController in the OrchardCore.Recipes module is slightly changed. If the recipe is a setup recipe (defined in the issetuprecipe of the JSON file) or has the hidden tag, the recipe will not appear in that list. You can see that our myrecipe has the false value for the issetuprecipe but the Blog recipe has the true value. Admin Dashboard Widgets We mentioned the Admin Dashboard widgets two times in This week in Orchard that allows you to add cards to the homepage of the dashboard, which is about to represent a piece of functionality of a given feature or module. You can find the first post here and the second one here. And now this feature has been merged to the dev branch of Orchard Core and there is also a new page in the Orchard Core Documentation about this module. It hasn't got too much information yet but the embedded recording could help you to see this feature in action. If you haven't heard about this feature, don't forget to check out the previous blog posts and the demo video! Use DocumentId in indexes This fix is also about using the correct combination of fields for each index that we use. For example, the index for the UserIndex table now contains every field of the table. So, from now you will find indexes for every index table. Refactor ContentZone - Tabs, Card, Column containers With more and more dynamic shapes coming into Orchard Core (all the tab/card grouping shapes, and also shapes like the ContentCard) it would be potentially useful to have a ShapesViewModel that could be used as a hard type abstract class to create specific targetted ViewModels, i.e. a TabViewModel. The problem with the ShapeViewModel is it doesn't support a list of positioned Items, so right now we are using Shape because many of these tab/card/content card shapes require a list of positioned items as well. So we was not intending that a ShapesViewModel was actually an IShape, just an abstract that could be used to build shapes with, and the mixin would still turn it into an IShape, by mixing in the ShapeViewModel which has all the required IShape properties. The idea being you could then use the IShapeFactory to create a shape, then add items to it. var shape = ShapeFactory.CreateAsync<TabViewModel>("Tab", m =>{ m.TabId = tabId});foreach(var item in thetabs){ shape.Add(item);} The current usage builds 3 different shapes, even when displaying on the front end, and there are no groups. Here we do a quick check first, to see if there are any groups, and if there are none, just render the zone directly. No extra shapes. Also Removes uses a dynamic, and moves to hard typed models. Uses ToLookup instead of GroupBy (better usage). Uses fewer dynamics for injected properties, i.e. DisplayAsync can be resolved directly to its interface instead of being dynamic (this needs evaluation, as we might do it for the other C# Shape Attributes, or not). If you check out the modifications of the ZoneShapes class, you will find the implementation of the ContentZone shape and building the TabContainer shape by using the new GroupingsViewModel. And by having the GroupingsViewModel ViewModel we can use that instead of a dynamic one as you can see in the TabContainer.cshtml file. Demos YesSql: Reimplement batching When we do updates on the content items and when one deletes a document all the index tables corresponding to the document type get a DELETE query. And this DELETE query is actually a single DELETE query. If we see a benchmark we can realize that the batching isn't working. So, if you would like to delete multiple content items, the code is just about to send multiple DELETE requests instead of sending one. If you run the query locally using SQL Server and you have 1000 indexes, it takes one second. So, you might not notice that it's slow. It's slow but it could look like that's because we have several indexes. Extra Indexes: 1, Elapsed 00:00:00.0371806Extra Indexes: 100, Elapsed 00:00:00.1317780Extra Indexes: 200, Elapsed 00:00:00.2826214Extra Indexes: 500, Elapsed 00:00:00.6213360Extra Indexes: 1000, Elapsed 00:00:01.2628232 But when you have the SQL Server in Azure, the deletion of 1000 indexes could take 28 seconds. At this point, you will start noticing the performance just after 100 indexes. Apparently, we have around 20 indexes in Orchard Core but you can quickly arrive at 100. Extra Indexes: 1, Elapsed 00:00:00.0838498Extra Indexes: 100, Elapsed 00:00:02.5644737Extra Indexes: 200, Elapsed 00:00:05.0814065Extra Indexes: 500, Elapsed 00:00:12.6558409Extra Indexes: 1000, Elapsed 00:00:28.6622291 In YesSql, when you update a document, it needs to update all the indexes, which means it will rebuild them. And an index can return multiple records like if I'm indexing the name of someone, I might want to index the first name, the last name, the middle name. These are three records, one per name. So, what it does is, it builds the three records in memory and it will send a query to delete any record that was associated with the document and then sends three inserts for the new records. So you have one for the delete and three for the inserts. But it sends a delete even for the indexes that didn't return anything because the fact that you didn't return anything might mean that there is nothing anymore associated. So you need to delete and send nothing. This way we get a delete per index. That's not optimal but that's how YesSql works and that's optimal for reads and not writes. To goal is to make reads faster than writes. Still, we should not have to send one independent query to do the deletes per index. That's what this issue is about. And Sébastien Ros managed to fix it. And here are some numbers. These are all for dummy indexes that never perform any writes. Just cause deletes. What we can see in the profiler is that everything easy to batch is batched together. The big batch with mostly deletes, and a couple of inserts, is now long-running, instead of many many short runs. Probably from the look of it, the insert is still expensive, so which pushes up the time run. Before batchingLocal Indexes 1, Elapsed 00:00:00.3004236 Indexes 100, Elapsed 00:00:00.2375774 Indexes 200, Elapsed 00:00:00.3583902 Indexes 500, Elapsed 00:00:00.7695818 Indexes 1000, Elapsed 00:00:01.2836934Remote Indexes 1, Elapsed 00:00:00.7207663 Indexes 100, Elapsed 00:00:03.3552247 Indexes 200, Elapsed 00:00:05.5547927 Indexes 500, Elapsed 00:00:13.8364514 Indexes 1000, Elapsed 00:00:27.2306443After BatchingLocal Indexes 1, Elapsed 00:00:00.2207824 Indexes 100, Elapsed 00:00:00.0910920 Indexes 200, Elapsed 00:00:00.1632908 Indexes 500, Elapsed 00:00:00.4007200 Indexes 1000, Elapsed 00:00:00.4559752RemoteIndexes 1, Elapsed 00:00:03.6326000Indexes 100, Elapsed 00:00:04.9639312Indexes 200, Elapsed 00:00:09.8273422Indexes 500, Elapsed 00:00:16.1340951Indexes 1000, Elapsed 00:00:15.2008296 And how it looks like is the following. If you create a blog post in Orchard Core and after the change, there is a single communication to the database that contains everything that you can see here. This contains creating the Document, creating the ContentItemIndex, updating the ContentItemIndex with the DocumentId, and so on. These are three indexes to update (ContentItemIndex, ContainedPartIndex and AutoroutePartIndex). insert into [Document] ([Id], [Type], [Content], [Version]) values (19, 'OrchardCore.ContentManagement.ContentItem, OrchardCore.ContentManagement.Abstractions', '{"ContentItemId":"4cpw0fnmjb1kp07dmzxx8n8ecg","ContentItemVersionId":"4953p18bj3gyy5yy82f7mj7w4y","ContentType":"BlogPost","DisplayText":"The title","Latest":true,"Published":false,"ModifiedUtc":"2020-12-31T00:31:34.3346095Z","PublishedUtc":null,"CreatedUtc":"2020-12-31T00:31:34.3346095Z","Owner":"48v9vt5vxznr5z9m1df9zmvjm8","Author":"admin","TitlePart":{"Title":"The title"},"AutoroutePart":{"Path":"blog/the-title","SetHomepage":false,"Disabled":false,"RouteContainedItems":false,"Absolute":false},"BlogPost":{"Subtitle":{"Text":"Subtitle"},"Image":{"Anchors":[],"Paths":[],"MediaTexts":[]},"Tags":{"TagNames":["Space"],"TaxonomyContentItemId":"4ykev5wxfcny7tvsahz9y64mwe","TermContentItemIds":["4nv0z7r24r1vw3sfpq7t6xws59"]},"Category":{"TaxonomyContentItemId":"4tpy2wv97bkbf0zkx8tyd1bm4q","TermContentItemIds":["4bsstr09f29rp0sgy85n9f07wj"]}},"MarkdownBodyPart":{"Markdown":"Some text"},"ContainedPart":{"ListContentItemId":"491emynv0kavbzhy40xmqv1wds","Order":0}}', 1);insert into [ContentItemIndex] ([ContentItemId], [ContentItemVersionId], [Published], [Latest], [ContentType], [ModifiedUtc], [PublishedUtc], [CreatedUtc], [Owner], [Author], [DisplayText]) values ('4cpw0fnmjb1kp07dmzxx8n8ecg', '4953p18bj3gyy5yy82f7mj7w4y', 0, 1, 'BlogPost', '2020-12-31T00:31:34', '', '2020-12-31T00:31:34', '48v9vt5vxznr5z9m1df9zmvjm8', 'admin', 'The title') ; select last_insert_rowid() [Id];update [ContentItemIndex] set [DocumentId] = 19 where [Id] = (last_insert_rowid());insert into [ContainedPartIndex] ([ListContentItemId], [Order]) values ('491emynv0kavbzhy40xmqv1wds', 0) ; select last_insert_rowid() [Id];update [ContainedPartIndex] set [DocumentId] = 19 where [Id] = (last_insert_rowid());insert into [AutoroutePartIndex] ([ContentItemId], [Path], [Published], [Latest], [ContainedContentItemId], [JsonPath]) values ('4cpw0fnmjb1kp07dmzxx8n8ecg', 'blog/the-title', 0, 1, '', '') ; select last_insert_rowid() [Id];update [AutoroutePartIndex] set [DocumentId] = 19 where [Id] = (last_insert_rowid()); When we create a blog post there aren't any delete requests, because there is nothing before but when we update we need to delete all the indexes and these calls contains unnecessary deletes because for example there is no LayerMetaDataIndex on the blog post but the logic here is hey, we are dealing with a content item and there is an index for all of the content items called LayerMetadataIndex. So it will send the delete just in case which is dumb. But you can see here for each index we have a delete and it used to be a single query communication query with the database. Now let's divide by two the part where we insert and update the indexes. Instead of having to insert something then update something for each index now, we have just inserted it. We still have all the deletes and some of them are still useless but these are quick. So we have just this request now when we update a single blog post. insert into [Document] ([Id], [Type], [Content], [Version]) values (23, 'OrchardCore.ContentManagement.ContentItem, OrchardCore.ContentManagement.Abstractions', '{"ContentItemId":"4cpw0fnmjb1kp07dmzxx8n8ecg","ContentItemVersionId":"4ypdrxm7xbndr0dvcpwaraa95g","ContentType":"BlogPost","DisplayText":"The title","Latest":true,"Published":false,"ModifiedUtc":"2020-12-31T05:55:56.8113646Z","PublishedUtc":"2020-12-31T01:22:37.7926461Z","CreatedUtc":"2020-12-31T00:31:34.3346095Z","Owner":"48v9vt5vxznr5z9m1df9zmvjm8","Author":"admin","TitlePart":{"Title":"The title"},"AutoroutePart":{"Path":"blog/the-title","SetHomepage":false,"Disabled":false,"RouteContainedItems":false,"Absolute":false},"BlogPost":{"Subtitle":{"Text":"Subtitle"},"Image":{"Anchors":[],"Paths":[],"MediaTexts":[]},"Tags":{"TagNames":["Space"],"TaxonomyContentItemId":"4ykev5wxfcny7tvsahz9y64mwe","TermContentItemIds":["4nv0z7r24r1vw3sfpq7t6xws59"]},"Category":{"TaxonomyContentItemId":"4tpy2wv97bkbf0zkx8tyd1bm4q","TermContentItemIds":["4bsstr09f29rp0sgy85n9f07wj"]}},"MarkdownBodyPart":{"Markdown":"Some text"},"ContainedPart":{"ListContentItemId":"491emynv0kavbzhy40xmqv1wds","Order":0}}', 1);delete from [ContentItemIndex] where [DocumentId] = 22;delete from [AliasPartIndex] where [DocumentId] = 22;delete from [LayerMetadataIndex] where [DocumentId] = 22;delete from [ContainedPartIndex] where [DocumentId] = 22;delete from [AutoroutePartIndex] where [DocumentId] = 22;delete from [TaxonomyIndex] where [DocumentId] = 22;insert into [ContentItemIndex] ([ContentItemId], [ContentItemVersionId], [Published], [Latest], [ContentType], [ModifiedUtc], [PublishedUtc], [CreatedUtc], [Owner], [Author], [DisplayText], [DocumentId]) values ('4cpw0fnmjb1kp07dmzxx8n8ecg', '4q3271jp1705etwnf52c0nnbwz', 1, 0, 'BlogPost', '2020-12-31T01:22:37', '2020-12-31T01:22:37', '2020-12-31T00:31:34', '48v9vt5vxznr5z9m1df9zmvjm8', 'admin', 'The title', 22) ; select last_insert_rowid() [Id];insert into [ContainedPartIndex] ([ListContentItemId], [Order], [DocumentId]) values ('491emynv0kavbzhy40xmqv1wds', 0, 22) ; select last_insert_rowid() [Id];insert into [AutoroutePartIndex] ([ContentItemId], [Path], [Published], [Latest], [ContainedContentItemId], [JsonPath], [DocumentId]) values ('4cpw0fnmjb1kp07dmzxx8n8ecg', 'blog/the-title', 1, 0, '', '', 22) ; select last_insert_rowid() [Id];insert into [TaxonomyIndex] ([TaxonomyContentItemId], [ContentItemId], [ContentType], [ContentPart], [ContentField], [TermContentItemId], [DocumentId]) values ('4ykev5wxfcny7tvsahz9y64mwe', '4cpw0fnmjb1kp07dmzxx8n8ecg', 'BlogPost', 'BlogPost', 'Tags', '4nv0z7r24r1vw3sfpq7t6xws59', 22) ; select last_insert_rowid() [Id];insert into [TaxonomyIndex] ([TaxonomyContentItemId], [ContentItemId], [ContentType], [ContentPart], [ContentField], [TermContentItemId], [DocumentId]) values ('4tpy2wv97bkbf0zkx8tyd1bm4q', '4cpw0fnmjb1kp07dmzxx8n8ecg', 'BlogPost', 'BlogPost', 'Category', '4bsstr09f29rp0sgy85n9f07wj', 22) ; select last_insert_rowid() [Id];update [Document] set [Content] = '{"ContentItemId":"4cpw0fnmjb1kp07dmzxx8n8ecg","ContentItemVersionId":"4q3271jp1705etwnf52c0nnbwz","ContentType":"BlogPost","DisplayText":"The title","Latest":false,"Published":true,"ModifiedUtc":"2020-12-31T01:22:37.6390174Z","PublishedUtc":"2020-12-31T01:22:37.7926461Z","CreatedUtc":"2020-12-31T00:31:34.3346095Z","Owner":"48v9vt5vxznr5z9m1df9zmvjm8","Author":"admin","TitlePart":{"Title":"The title"},"AutoroutePart":{"Path":"blog/the-title","SetHomepage":false,"Disabled":false,"RouteContainedItems":false,"Absolute":false},"BlogPost":{"Subtitle":{"Text":"Subtitle"},"Image":{"Anchors":[],"Paths":[],"MediaTexts":[]},"Tags":{"TagNames":["Space"],"TaxonomyContentItemId":"4ykev5wxfcny7tvsahz9y64mwe","TermContentItemIds":["4nv0z7r24r1vw3sfpq7t6xws59"]},"Category":{"TaxonomyContentItemId":"4tpy2wv97bkbf0zkx8tyd1bm4q","TermContentItemIds":["4bsstr09f29rp0sgy85n9f07wj"]}},"MarkdownBodyPart":{"Markdown":"Some text"},"ContainedPart":{"ListContentItemId":"491emynv0kavbzhy40xmqv1wds","Order":0}}', [Version] = 1 where [Id] = 22;insert into [ContentItemIndex] ([ContentItemId], [ContentItemVersionId], [Published], [Latest], [ContentType], [ModifiedUtc], [PublishedUtc], [CreatedUtc], [Owner], [Author], [DisplayText], [DocumentId]) values ('4cpw0fnmjb1kp07dmzxx8n8ecg', '4ypdrxm7xbndr0dvcpwaraa95g', 0, 1, 'BlogPost', '2020-12-31T05:55:56', '2020-12-31T01:22:37', '2020-12-31T00:31:34', '48v9vt5vxznr5z9m1df9zmvjm8', 'admin', 'The title', 23) ; select last_insert_rowid() [Id];insert into [ContainedPartIndex] ([ListContentItemId], [Order], [DocumentId]) values ('491emynv0kavbzhy40xmqv1wds', 0, 23) ; select last_insert_rowid() [Id];insert into [AutoroutePartIndex] ([ContentItemId], [Path], [Published], [Latest], [ContainedContentItemId], [JsonPath], [DocumentId]) values ('4cpw0fnmjb1kp07dmzxx8n8ecg', 'blog/the-title', 0, 1, '', '', 23) ; select last_insert_rowid() [Id]; Using the other PR we are able to teach the index when not to send deletes as there will never be any index related to this Document, so don't send deletes. After that, you can see there is no more LayerMetaDataIndex and no more AliasPartIndex calls because the blog post doesn't have these. delete from [ContentItemIndex] where [DocumentId] = 23;delete from [ContainedPartIndex] where [DocumentId] = 23;delete from [AutoroutePartIndex] where [DocumentId] = 23;delete from [TaxonomyIndex] where [DocumentId] = 23; This is by having a new method on the IndexProvider to explain when to not use the IndexProvider. So it would not even go to the Map method. In this case, we say if you don't have the AliasPart, don't use the IndexProvider. context.For<AliasPartIndex>() .When(c => c.Has<AliasPart>()) .Map(contentItem => Check out the following recording on YouTube to know more about this YesSql improvement! News from the community Lombiq Hosting - Azure Application Insights This new Orchard Core module from Lombiq enables easy integration of Azure Application Insights telemetry into Orchard. Just install the module, configure the instrumentation key from a configuration source (like the appsettings.json file) as normally for AI, and collected data will start appearing in the Azure Portal. Would like to learn more about our new module? Then head to the repository now where you can find every detail about how to set up and use that module in your site! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 191 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 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!

Distributed cache, Media crop picker - This week in Orchard (08/11/2020)

This week we will see the new IDocumentStore, which is a cacheable, committable, and cancellable document store allowing to get documents from a shared cache. And don't forget to watch a demo about how you can add an alt text and crop the images of your Media Field! Orchard Core updates Make features actions sticky while scrolling If you navigate to the admin UI of Orchard Core and head to Configuration -> Features, you will see all of the currently available features of Orchard Core. This list is now getting longer and longer, so the idea here is to use a sticky bar on scrolling for very long pages instead of the scroll to top button. The first page that gets this sticky bar is the Features page, which looks like the following now. Edit button for lists in DetailAdmin view This is a feature that was already there in Orchard 1. When you want to edit something in the admin, you can return a route to the controller that will edit an entity. Or that will display it as a list or display it as a detailed object in the admin. And when you have a list, you have two options. Either you want to show all the content of this list or you want to actually edit the list itself. And to do that, when you see a blog and you click the link of the blog in the content items, it will go to the list of blog posts. This is the DetailAdmin view. And if you actually want to edit the blog you need to click on the edit button. This feature is about adding a new button for the list and you are now not confused about clicking the link or click in the properties button. Move feeds to feature There is a new feature now in Orchard Core called Feeds. Don't forget to enable that module if you would like to have feeds capabilities on your site! Generate xml documentation (comments) for nuget packages Whatever documentation we put on the files, they were not available, because if you don't put the GenerateDocumentationFile tag then it's not generated in the XML file that contains all the documentation, it's not embedded into NuGet, and Visual Studio won't load it. You need that to export your API docs. Not even to generate documentation, just to be able to have it in the NuGet package for the IntelliSense. If you don't do the NoWarn, every public member that doesn't have an API doc would fail the build. The <NoWarn>$(NoWarn);CS1591</NoWarn> removes the warning that some public members do not have comments. Now you will have more documentation when they use the NuGet packages to build sites! Distributed cache Whenever you want some cacheable document that is stored in the storage using YesSq for instance you need to inject the IDocumentStore interface. This will use YesSql to load the document and it will be able to cache it. So, for instance, if you would like to get the site settings you can use the IDocumentStore to do that because it's stored as a document and you want to cache it. And then when you load the site settings using IDocumentStore by passing the type, you can say GetOrCreateImmutableAsync or GetOrCreateMutableAsync. Mutable meaning that when you load the site settings just to read it, you want to say I want an immutable object. And when you want to load the site settings to update it, then use the GetOrCreateMutableAsync method. The difference is in the way that it will either cache it or not and also would it take it from the cache or not, or put it back in the cache or not. Or invalidate the entry in the cache. And there is the IFileDocumentStore which has the same methods as the IDocumentStore, but it's a totally different service. This one can be used to store a document on the file system that can be also cached. But it's a different store. We use the IFileDocumentStore to store the content type definitions. Demos Media crop picker and Alt text editor Set up your site using the Blog recipe. That recipe comes with the Blog Post content type that has the Banner Image Media Field by default. Let's check out the predefined blog post content item to see the new features of the Media Field. If you select the post-bg.jpg image and click on the button with the speech bubble icon, you can set the alt text for the image. Another new button is doing a more interesting thing. If you click on the button with the target cross icon, another new modal window will open where you can select the anchor for the selected image. Using the target cross, you can easily specify the crop point of the image. If you open the preview in another window you can easily see the changes of the image in real-time. But how you can enable/disable these options? Navigate to Content -> Content Definition -> Content Types and hit Edit near the Blog Post and edit the Banner Image settings. Here you will find two new options. One is about allowing alt text and one is to allow the center cropping. These are on by default, that's why you could see the mentioned buttons when you edit the media field. And that's not all! If you would like to know more about this feature don't forget to check out this recording on YouTube! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 172 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 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!