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

Centralize the Indexing process, Remove Media files for a removed tenant when using Azure Blob Storage - This week in Orchard (20/06/2025)

This time, you can see a demo about centralizing the Indexing process and having a unified UI for managing Indexes and the Search Settings! But first, let's look at our other topics, like removing Media files for a removed tenant when using Azure Blob Storage, and adding RouteEndpoint cache. Don't forget that you can still fill out our Orchard Core Admin UI experience renewal survey to help shape the future of Orchard Core!

Latest tutorials

Featured tags

IIS
API
SMS
SEO
MCP
All tags >

Admin Dashboard, Display titles in the top bar - This week in Orchard (24/12/2020)

Option to display page titles in the top bar on the admin UI, documentation for external libraries, new FileDocumentStoreAttribute, and a lot more are waiting for you in our last blog post for this year. Let's get started! Orchard Core updates Display titles in the top bar Set up your site using the Blog recipe, then navigate to the admin UI of the site. Head to Configuration -> Settings -> Admin. Here you will see a new option, called Display titles in the top bar. Let's put a tick here and see what will happen. If you save it, the titles will be placed in the top bar of the admin theme. The only thing you have to do is to slightly modify the appearance of the title of your page in the admin UI by making sure to put it in the Title zone. <zone Name="Title"><h1>@RenderTitleSegments("My page")</h1></zone> So, if you set that you would like to display the title in the top bar, then the Title section will be rendered in the top bar section of the theme, otherwise, it will stay in its own place. Hide connection string when already set for the tenant When a connection string is defined in an environment variable, the value is displayed on the Tenants creation page: $env:OrchardCore__ConnectionString="server=localhost;uid=root;database=db;password=my-secret-pw;"$env:OrchardCore__DatabaseProvider="MySql" Now if the connection string is coming from the configuration in the setup screen, then it's not displayed anymore, and this way we can't change it. The SetConfigurationShellValues method in the AdminController of the OrchardCore.Tenants module checks the values of the shell settings based on the ConnectionString and DatabaseProvider keys and if there are any, the EditTenantViewModel will get these values. And now we can only show the given sections on the front-end if these values haven't been set from the shell settings. External libraries documentation Orchard Core uses several external .NET libraries, like Jint, YesSql, and Fluid. But you can find several Client-side libraries here too, like GraphiQL, TypeScrip, React, or Vue. The goal of this new page in the Orchard Core documentation is to list all of the used libraries with their version. FileDocumentStoreAttribute providing a FileName By default, the file name is equal to the name of the related document type, e.g. ContentDefinitionRecord => ContentDefinitionRecord.json. So, for compatibility, this attribute allows keeping the current ContentDefinition.json without having to manage this specific case in FileDocumentStore with a hard-coded string. Add the email optional claim steps to AAD integration document If you follow this how-to guide, you can build a blog that allows users to login with their AzureAD account and gets assigned roles based on the Security Groups they belong to. However, the documentation hasn't mentioned yet how to set up optional claims to configure additional information when you are registering a new application (App registration) on the Azure Portal. Now this how-to has been updated with the way how you can add optional claims (like email) to your configuration. Demos Admin Dashboard To see this new feature the only thing you have to do is to just simply set up your site and navigate to the admin UI. After you will get a screen something like this. Here you can see cards, that are dashboard items, that are about to represent a piece of functionality of a given feature or module. For example, the one called Content items is coming from the Contents module and by using that, you can easily do some content-related functions (like listing the latest or the draft content item). It's pretty straightforward, so let's look under the hood to see how you can create your own dashboard items. But first, let's see how the site renders the items on the homepage of the admin UI. The AdminDashboard.cshtml in the OrchardCore.Admin module is just about to display the SummaryAdmin display type of every AdminDashboardItem that can come from any module. Let's see the first card with the title Content items. If you open up the Views folder of the OrchardCore.Contents module, you will find a view with the filename AdminDashboardItem.SummaryAdmin.cshtml. Here you can see the HTML structure of a Bootstrap card item with the custom content inside it, which in our case is some links to the AdminController in this module. We have a driver too to say display the SummaryAdmin display type and place it in a given location. That's all you have to do to have a new card on the homepage of the admin UI. This feature is under development and might be changing in the future. And it has been already changed just before we finalized this blog post. :) But what are the exact changes here? Well, that will be covered in an upcoming post, stay tuned for that! If you would like to know more about this, check out this recording on YouTube! News from the community A new website using Orchard Core: AeroSpace Cornwall AeroSpace Cornwall is a research, development and innovation fund, that enables businesses to take their idea and turn it into a viable product ready for market in the space and aerospace sectors. Check out this site to see the loads of capabilities that you can achieve using the CMS. 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. It was started by Ryan Drew Burnett, but since he doesn't work with Orchard anymore, as announced earlier it is now maintained by our team at Lombiq Technologies. Our full Orchard Core tutorial series, the Dojo Course 3 is here! After a long wait, the new Orchard Core version of our legendary Dojo Course tutorial series is here, the Dojo Course 3! Are you a newcomer and want to learn Orchard Core from the ground up, both from a user's and a developer's perspective? Are you somewhat familiar with Orchard Core but would like to get up to speed and become an Orchard pro? Look no further, check out Dojo Course 3! Dojo Course 3 guides you from the very basics of Orchard Core all up to be able to write your own themes and modules, utilizing various APIs of Orchard. We're publishing a tutorial video every day for 40 days starting on 1 December. So, this is your 40 days of Orchard :). Videos about Orchard Core development are on the way, you can see a new one every day! If you are really interested in the coding part, the upcoming, almost 20 videos are specially for you. If you're looking for our previous Orchard 1.x tutorial series check out Dojo Course 2. Christmas in Lombiq Sometimes we do stuff. Together. Not (just) in front of computer screens. These are some usual events in Lombiq that are all announced and arranged in advance. We periodically have an event called RnDay: this is a few hours long event where we share with each other what we recently worked on and what we plan to do. E.g. if we recently finished a project then the project's team members demo what they've done. Last week we had our last RnDay for this year but this time we have to make it online. We also named this event to The 13th RnDay - Pandemic Edition! We also tried to do our best to make a nice group photo, you can see the result down below. :) We would like to thank you all for reading our posts and making the Orchard community stronger together with us! We hope that we could give you valuable news and demos about the happenings around Orchard and Orchard Core from time to time by reading our posts and of course the This week in Orchard newsletter. We would like to wish everyone a Merry Christmas and a Happy New Year! See you next year! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 178 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!

User Picker Field, the new user ID - This week in Orchard (06/12/2020)

This time we will do a little deep dive and check out some important changes in the code base of Orchard Core. But don't be scared, we promise you will like these changes, especially the demo about the new User Picker Field! Orchard Core updates Allow media width and height values without a token You could see a demo a few weeks ago in this post about the new options for Media Field where you can set the alt text of your image and you can also crop your images using a nice media crop picker. The way it was working is it's putting different kinds of options to the query string that allows you to manipulate your image. Let's see the following URL for an example: https://localhost:44300/media/post-bg.jpg?width=1&height=600&rmode=crop&rxy=0.2,0.5. Here you can see we set the width and height of the image from the media library. We also set the resize mode for the processed image with other parameters as well. A few days later the community introduced a new bool option added to the MediaOptions called UseTokenizedQueryString to encrypt the image processing query string to prevent disc filling, that is true by default. And now here comes another great stuff that allows values for width and height to be provided via the query string even when tokens are enabled. What does it mean? Let's see an example of it! Set up your site using the Blog recipe then open the default banner image URL of the predefined blog post with the following query string parameters: https://localhost:44300/media/post-bg.jpg?width=1024&height=600. Note that the tokens are enabled by default, but you can still set the width and the height of the image now. Don't forget that this will only work if the height and width values match the supported sizes array values. Introduce Culture Scope There is a new CultureScope class that you can use if you want to locally set the current culture (the current user interface culture and the culture used by the current thread). You can find several unit tests to see how you can use it, but check out this one for now. Here you can see that the culture is set to French, but that setting only applies inside the using statement. Implement UserId All the user profiles that you have locally, now have a new property called UserId, which is unique. We used to use a name, the user name as the way to identify a user. But now the community decided to use a unique ID such that you can't guess user ID or you can't recover another set or permission or ownership by mistake, because an account has been deleted and someone created a new account using the old name and somehow the logical references are still kept based on this name and you would inherit something from that. So, to prevent that, Orchard Core is using now a user ID. If you take the latest version of the dev branch and just run your code there will be a migration that copies the user names of the existing users as the user ID. This way you don't have any change in your content, it will still work the same and be careful that your user ID equals a string like 4gq8jagmrtxrwvg21csa0b6y4y, which is safe, because the next time someone creates a new user, they can't impersonate anyone else like recovering an old account, because it will be a newly generated unique identifier that can't match something like that. And how can you find the currently logged in user? Check out the code in the DefaultContentsAdminListFilter where you can see that now, instead of using the user.Identity.Name, you can use the FindFirstValue extension method from ASP.NET Core to return the value of the first instance of the specified claim type, or null if the claim is not present. And then you can set that value as the Owner of the content item. Demos User Picker Field Let's say you would like to create a blog where multiple users can create blog posts and you want to connect the user account of the author user with the given blog post by showing the name of the user somewhere in the detail view of the post. It's easy because the users can log in to the admin UI of Orchard Core and publish their own posts. In this case, they will be the authors of the given content items. But let's say we don't want to give them access to the site. We just want them to send the content of the blog post to a given email address and the site editors will edit and publish the posts. Is there an easy way to connect content with user accounts in Orchard Core? Set up your site using the Blog recipe. This recipe comes with a predefined blog where you can create new blog posts. The posts can have several properties: the title, the banner image, tags, the category, and so on. We will modify the content definition of the Blog Post to do some tricks. Navigate to the admin UI of Orchard Core and head to Content -> Content Definition -> Content Types and edit the Blog Post one. Click on the Add Field button and find the recently added one, called User Picker Field. This field allows you to connect users with a content item. Here you can say that you want to allow multiple users to be selected, allow the picker to display users from all roles, and many more. If you put a tick on the Display All Users checkbox, every user will be in the list that you can choose from, if you remove the tick, the available roles in the system will be listed and you can choose from them. Now if you edit the predefined blog post, you will see the User Picker Field in action. In this case, we have two users in the system named admin and editor. The admin is the superuser with the Administrator role and the editor user has the Editor role. We can see both of them because we said we would like to allow the picker to display users from all roles. If you save your content item, the field will show you the user names of the selected users seperated by a comma (if you selected multiple ones). And you will see a No users. message is you haven't selected any users. You can find some lines about the User Picker Field in the documentation of Orchard Core and a nice presentation of this feature on YouTube! News from the community Our full Orchard Core tutorial series, the Dojo Course 3 is here! After a long wait, the new Orchard Core version of our legendary Dojo Course tutorial series is here, the Dojo Course 3! Are you a newcomer and want to learn Orchard Core from the ground up, both from a user's and a developer's perspective? Are you somewhat familiar with Orchard Core but would like to get up to speed and become an Orchard pro? Look no further, check out Dojo Course 3! Dojo Course 3 guides you from the very basics of Orchard Core all up to be able to write your own themes and modules, utilizing various APIs of Orchard. We're publishing a tutorial video every day for 40 days starting on 1 December. So, this is your 40 days of Orchard :). In the first few videos, we gave you an introduction to Orchard Core and showed you a way about how to set up your first Orchard Core website. After we started to talk about the content model of Orchard Core, checking out the basics of content management. We will stay in the admin UI for a little in the upcoming days and check out the other basic features of the CMS like how to add widgets with layers, managing the menus, and the media files. After we will see how can you search and index content items, and build forms using the Forms and Workflows feature. But we will not spoil the topics of the upcoming videos. :) If you're looking for our previous Orchard 1.x tutorial series check out Dojo Course 2. 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!

Dark mode admin theme, new locale Shortcode - This week in Orchard (20/11/2020)

The dark mode for the admin theme is here! But first, let's check out the new locale Shortcode, the new Select HTML tag in the Forms module, and many more! Orchard Core updates New locale Shortcode This Shortcode will take the text between the tags and only display it if the current culture is the one specified. In this case, write English Text for the English culture and write French Text for the French culture. It also supports culture fallbacks. So, if your culture is en-CA and you would like to show the French text, it will fall back to en. Note that it's not content localization, it's just text localization that you want to use in your templates. Read more about it in the docs! [locale en]English Text[/locale][locale fr]French Text[/locale] New HTML select tag with options for Forms Set up your site using the Agency recipe. Then navigate to the admin UI of Orchard Core and head to Configuration -> Features to enable the Forms module. Now create a new Page content item. This content type has a Flow Part attached and because of that, we can add widgets to this content item. We added a new Form widget here and inside the Form, we added the new Select widget. By using the Select widget, you can have an HTML <select> tag that creates a drop-down list with the options you provided. In this case, we created a Donation drop-down list with two options. You can also predefine the option you would like to be selected by default. Listing Code owners When submitting a PR updating code you're not familiar with, it's not always easy to determine who's the right person to be assigned to for review. To fix that, the community established a list of code owners who will be automatically pinged when the code they own is updated by a PR. Read more about the code owners feature of GitHub here! Add classes / IDs to buttons in admin to allow easier selection in E2E tests This improvement is about adding IDs and classes to different HTML tags in the admin interface. This will allow us to write better selectors for E2E testing. So from now on, if you would like to target specific elements of the admin UI, like buttons to enable or disable a given feature or to run a given recipe, you will have an easier way to do that, because of the additional classes and IDs that you can find in the HTML source code. Recommended development tools for Orchard Core What tools do we recommend to build your app with Orchard Core, or work on Orchard itself? In the end, this is up to your personal preference since as long as you can edit source files and build the app you can use any tool on any platform that .NET Core supports. Check out this page in the documentation to get you going for the general editing experience as well as for other useful tools. Orchard Dojo Library is a portable package of coding and training guidelines and development utilities. These are also part of the best practices and guidelines we use at Lombiq. This library contains Visual Studio code snippets to quickly generate code in some common scenarios for developing Orchard Core modules and themes. To effectively use this collection of VS snippets just point the Snippets Manager to where you cloned or downloaded this folder. To do this, go to Tools → Code Snippets Manager → select the C# language → Add and add the whole folder. For Razor snippets to also work select the HTML Language and do the same. Do note that Razor snippets will only be suggested when you hit Ctrl + space first. You can download the snippets from this GitHub repository and check out this recording to see more snippets in action! Add support for sending email attachments You can use the SendAsync method from the SmtpService to send emails from Orchard Core. The MailMessage class represents a class that contains information about the mail message. And now this class has a new property called Attachments which is a collection of message attachments. Use the MailMessageAttachment class to provide attachments by setting the attachments' filename and the attachments' file stream before calling the SendAsync method to send out your email. Demos Dark mode admin theme Set up your site and navigate to the admin UI. Then go to Configuration -> Settings -> Admin and check Enable dark mode admin theme. If you save the setting you have the option to toggle dark mode for the admin theme. If your OS is using dark mode, it will automatically applies the dark mode theme for you. You might notice that there is a new button in the upper-right corner of the admin theme with different icons: Sun and Moon represent the light and dark mode, respectively. If you switch to the dark mode the admin UI will have the following look and feel. But that's not all of it! Check out this recording on YouTube to know more about the dark mode! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 168 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!

New full_text Liquid Filter, Media Field improvements - This week in Orchard (14/11/2020)

See the improvements of the Media Field, the new full_text Liquid Filter, the enhancements of the admin UI, and many more in our upcoming post! Orchard Core updates ListContent Permission as Content Type dynamic permission Install your Orchard Core site with the Blog recipe and head to the admin UI. Navigate to the Security -> Roles and hit Edit near one of the roles. Type list in the search box that will list you some new permissions: the new ListContent permission on each Content Type. However, the global ListContent permission is of course priority over these. That means now you can decide which content items you want to list to the users in the given roles by using this dynamic permission. New full_text Liquid Filter Now there is a new Liquid filter called full_text. This lets you extract the full-text aspect of a content item. A full-text aspect being like metadata that we can get from any content item to represent it as full text. The goal being to be able to define custom full text for custom content types that will themselves use a full text of subitems. Let's say you have a Bag Part and you want to make your full text comprised of every full text of the items that you have in the Bag Part. To do that you can do a foreach on every item in the Bag Part and then you can call into their full text to provide it. Sticky bars on top while scrolling Last week we mentioned that the Features page has a new sticky bar on scrolling for very long pages instead of the scroll to top button. The good news is now more and more pages get this sticky bar on the admin UI. The Content Types page (Content -> Content Definition -> Content Types), the Content Parts page (Content -> Content Definition -> Content Parts), the Tenants page (Configuration -> Tenants), the Users page (Security -> Users), and the Recipes page (Configuration -> Recipes) are now also have a sticky bar. Fix double encoding of non-HTML strings in feed You can use the PopulateAsync method of the CommonFeedItemBuilder to build the RSS feed items using your content items. The RSS feed items have several properties like the link, guid, title, description, and so on. When we set the value of the title by calling the feedItem.Element.SetElementValue, the text that we pass will be encoded, so we don't need to encode it again, otherwise, we get it encoded twice. The same issue has been fixed in the ListFeedQuery feed query provider too. Initializing Liquid Include Filter There is an Include tag in Liquid that allows you to include an external Liquid file and in Fluid it's available through a FileProvider property, and in this case, the FileProvider property of the ILiquidFileProviderAccessor will be assigned to the LiquidTemplateContext. That means you can use it in your modules and your embedded assets. But how can you use that Include filter? Include your Liquid file using the {% include "Areas/TheBlogTheme/Views/Test" %} expression. This will include the Test.liquid file from the Views folder of the Blog theme. Demos New Media Field option to encrypt the image processing query string You could see a demo last week about the new options for Media Field where you can set the alt text of your image and you can also crop your images using a nice media crop picker. The way it was working is it's putting different kinds of options to the query string that allows you to manipulate your image. Let's see the following URL for an example: https://localhost:44300/media/post-bg.jpg?width=1&height=600&rmode=crop&rxy=0.2,0.5. Here you can see we set the width and height of the image from the media library. We also set the resize mode for the processed image with other parameters as well. Now there is a new bool option added to the MediaOptions called UseTokenizedQueryString to encrypt the image processing query string to prevent disc filling. That's true by default so you can try it out right away! To do that just simply open the predefined blog post and view the page source in your browser. Find the header HTML tag, where you can see how Orchard Core sets the URL of the background image. And that's not all of it! If you would like to know more about this feature, don't forget to check out this recording on YouTube! Orchard Core OpenID Connect Code Flow Api BlazorWASM We mentioned the Blazing Orchard project two weeks ago here in This week in Orchard that is a modular application framework that turns your Blazor project into a CMS-powered Blazor application by leveraging Orchard Core as a decoupled backend/CMS server using its REST & GraphQL APIs. In this demo, you will see a solution, that contains an updated version of Blazing Orchard that also contains OpenID Connect Authentication! Head to YouTube now to see the recording of this demo! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 169 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!

Blazing Orchard, Replace and Delete Content Definition Deployment Steps - This week in Orchard (30/10/2020)

Blazing Orchard is a modular application framework that turns your Blazor project into a CMS-powered Blazor application by leveraging Orchard Core as a decoupled backend/CMS server using its REST & GraphQL APIs. Check out our current post to read more about Blazing Orchard and many more! Orchard Core updates Introduce Replace and Delete Content Definition Recipes The Content Definition Recipe deployment step always merges settings. When using this on a dev/stage/prod environment this means arrays, like BagPartSettings and FlowPartSettings are merged. When you've removed a content type on dev, and removed it from the BagPartSettings this change is not reflected on the server when the content definitions step is running. What also happens is the widget content type definition also remains, as the recipe only focuses on updating the definitions in the step. Of course, this is good for the scenario where definitions may have changed on both servers, and for bringing them into sync (kind of, but that scenario gets a bit confusing). But don't worry! Here comes two new deployment steps and recipes to the rescue! Replace Content Definitions: Replaces or Creates Type and Part Definitions. Delete Content Definitions: Allows a comma-separated list of types and/or parts to delete. Let's check them out! Set up your site using the Blog recipe then navigate to the Configuration -> Import/Export -> Deployment Plans and create a new deployment plan. Hit the Add Step button if you are ready and search for the Replace Content Definitions step in the Available Steps modal. Here you can see a list containing all of the available content types and content parts that you have in your tenant. If you choose something from the list, the type and part definitions will be removed and recreated. The Delete Content Definitions deployment step is just about to delete your content type and content part definitions. Remove type="text/javascript" from script tags The W3C validator checks the markup validity of Web documents in HTML, XHTML, SMIL, MathML, etc. The validator found a warning in an Orchard Core site that says: The type attribute is unnecessary for JavaScript resources. If you open up the MDN web docs by Mozilla you can learn more about the script element. Add ShapeResult - RenderWhen The problem is that SummaryAdmin shapes are added during BuildDisplayAsync so the conditions will be evaluated for every front-end BuildDisplayAsync display, even though they're only intended to be placed in a SummaryAdmin display. The goal here to add a Func to the ShapeResult that can be invoked after placing a shape in a location, to evaluate whether it should be placed. This would mean that for all of the SummaryAdmin shapes the RenderWhen will only run after they have been placed in SummaryAdmin. So the evaluation will not occur during a Detail or Summary view on the front end. The AuthorizeAsync isn't a super heavy call, but we often want to conditionally evaluate in a driver whether to return a ShapeResult so it makes sense to have something that can be applied later in the BuildDisplayAsync pipeline when we know that we are actually going to place the shape in a location. The ContentsDriver renders the ContentsButtonActions_SummaryAdmin shape, that is responsible to display the Publish, Preview, Unpublish, etc. buttons. You need to have some permissions to be able to see these buttons. See the refactored logic here using the RenderWhen method. Adding ID for FormPart Now there is a new content part called FormElementPart that turns a content item into a form element by providing an ID to the form. Now the built-in Form widget has this part attached meaning that when you add the Form widget to a FlowPart, you can define an ID. And here comes the modifications in the Form.Wrapper.cshtml wrapper. If the content item has the FormElementPart attached, then get the ID from that and use it as the ID for the form HTML element. Demos Blazing Orchard Blazing Orchard is a modular application framework that turns your Blazor project into a CMS-powered Blazor application by leveraging Orchard Core as a decoupled backend/CMS server using its REST & GraphQL APIs. Orchard Core is used here as a headless CMS, which means that Orchard Core is a separate application in the solution. The Blazor application is also a separate project. Therefore you need to host these two separately in a separate container for example. Clone the repository of the solution and check it out yourself! The structure is the following. The BlazingOrchard.Web.Application is shared by both the Blazor client host (BlazingOrchard.Web.Client) and both the server (BlazingOrchard.Web.Server). Let's see how you can render stuff with the help of Blazor in this solution. Check out how the menu rendering works! There is a NavMenu component (NavMenu.razor) in the Shared folder of the BlazingOrchard.Web.Application project, which comes with the default placement template. But here we are using a custom component (Menu.razor) that comes from the BlazingOrchard.Menu library. This thing is also using another component called ContentItemView, which gets the data from Orchard using an HttpClient. It's reusable, which means you can use this in other components too, like in the ContentPage component. Let's navigate to the server and manipulate the menu items of the Main Menu by adding a new Link Menu Item to it called Readme. Now you can see that the menu structure has been updated in the Blazor application. Or let's see the CounterButton component. This piece of code is about having a currentCount int variable to store how many times the user clicks on that button. The IncrementCount method is responsible to do the business logic for this. If you navigate to the Orchard Core server and create a new Liquid Page, you can use Liquid expressions to render this component. To do that, you can just simply add the following Liquid expression to the body of the content item: {{ "CounterButton" | shape_new | shape_render }}. Notice that here we are creating a new shape based on the CounterButton component and render it in the body of the Liquid Page. The CounterButton component has a public ButtonText parameter. And - because we are dealing with shapes here - you can set the value of that variable by providing it in Liquid when creating the shape like: {{ "CounterButton" | shape_new: ButtonText: "Click on this button!" | shape_render }}. This way we can use the CMS to configure these components. And you can do a lot-lot more using this PoC solution thanks to its creator, Sipke Schoorstra! Head to YouTube and check out the recording of this demo now to know more about what you can achieve by using this solution! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 167 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!

VueForms module, Obsolete IContentAliasManager - This week in Orchard (22/10/2020)

We prepared with a huge demo about showing you how you can use the custom VueForms module for Orchard Core! But first, let's check out the latest news around Orchard Core. Read our current post to find out an obsolete interface! Orchard Core updates Fix sizing of HTML/MarkdownEditor settings to be consistent in the correct zones There were some inconsistencies with the sizing of some field elements settings and other views. Some hints were full-width, some were restricted to col-md-6, other col-sm-6. Hint boxes should also align together with the rest of the fields.And one more thing here: the general settings/common to all editors should be in the Content zone and editor modes should be in the Editor zone. The issues had been fixed, they all look like this now, without uneven padding, and shapes are consistently ordered. Obsolete IContentAliasManager The IContentAliasProvider was renamed to IContentHandleProvider. The idea behind that is the alias was a bad name because it was in conflict with the AliasPart and they are two different things. They are related somehow because a handle now can come from an alias, but a handle is a generic term to say you can get a content item from different ways, like using a content item ID or a slug or alias. Whatever kind of identifier you want to give to your content item and then when you load a content item by its handle, you provide a prefix. In the past, the IContentAliasManager was just marked as obsolete and make it backward compatible, but the backward compatibility code didn't work. So, don't forget, if you injected the IContentAliasManager in the past and you update your Orchard Core solution to the latest, you will need to use the IContentHandleManager instead. Ensures shell terminating and disposing When e.g. we enable a feature for a given shell through the admin, the shell is released in the context of a shell scope, and at the end of this scope (if it is the last one for this shell) the terminate events are called and then the shell is disposed. But when e.g. we reload a tenant through the admin or when a shell releases its dependents, a shell may be released without having any current scope on it, so it is disposed immediately but without calling the shell terminate events. So here, in that case, we create a new scope (without using it) and dispose it to let it manage the shell state as usual. Note: In that case, the terminate events are called synchronously, we would need a shell ReleaseAsync(), but at least there are called. Another suggestion would be to get rid of the terminate events that are not used in the current code. So, in summary Here we ensure that the shell terminating/terminated events are called, even if the shell is not terminated by the last shell scope, e.g when the shell is released by dependency or when changed through the tenant's admin UI. So, right now we kept the terminate events. Here we also call the shell terminating/terminated events before the BeforeDispose callbacks that we use to call the session commit asynchronously, which is better if a terminate event uses an ISession. Demos VueForms module 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 VueForms, which aims to simplify the creation of client-side forms in OrchardCore. Let's see that module in action! Clone this repository and set up your site. Now go to Configuration -> Features and enable the VueForms and the VueForms Localized modules. The first is about provide a Form content type that simplifies using VueJs forms in the frontend and the second one is about to weld the LocalizedText part to the VueForms. The difference between the built-in Forms module and this one is that it's using client-side validation using Vue.js, Vuelidate, and Vuetify. Now if you navigate to the Content menu option, you will find a new one called Vue Forms. Here you can manage your Vue Form content types. Let's create a new one called Contact us! You have the option to disable or enable your form. If you disable the form, you can set an HTML, that is displayed when someone tries to render a disabled form. This feature is about creating the form on the back-end and no one can access it on the front end. If the server-side validation passes you will get the message that you can provide in the Success Message text box. Or it's doesn't, you can display the text that you can type in the Error Message textbox. Next one is the client init script. This is actually a client-side JavaScript, where you can set client-side actions. Right now here we set the required fields and in this case, we use it to localize the VeeValidate field validations. The required messages are coming from our localize liquid filter. The OnValidation is a server-side script, this is using Jint. Here you can get the form data and then you can perform validation here. This is not complete yet, the end goal would be to have widgets and the validation would be placed inside the widgets. The widgets would generate the client-side and server-side validation together. The addError() method allows you to add an error and map that input into the client-side. Here comes the OnSubmitted section. This is where you would perform actions after validation. Let's say the validation passes, there are no errors added, that means this script is called. In this case, we are creating a new predefined ContactRequest content item. And in the Localized Text section, you can create localizations with a key-culture pair. Here you can add as many as you want by clicking on the Add button, you can delete them by clicking on the trash bin icon, and reorder them with the little hamburger icon. The getLocalizedTextValues() function in the OnValidation section is used to get the localized text for the current culture that you defined here. This content type has a Form Part too that you can use to add a new Vue Component widget. Using that you can set the VueJS Component template. It's basically code, you are writing your Vue.js component here. You provide the template and you also have the script that is a typical Vue.js component script. The template is using the ValidationProvider component that wraps your inputs and provides a validation state using scoped slots. Now let's publish this new content item and view it in the front-end! Here you can see we have already filled out this form with some data but the email address is wrong. If we click on send, we will get the Your email is invalid error message, which is a client-side validation error. But that's not all! Enable the Workflows module and create a new workflow type called VueForm submitted. Click on the Add Event button and you will find a new category in the modal window called VueForm. And there is a new VueForm Submitted event that is fired when a VueForm passed validation and is submitted. Here you can also select the forms for which this workflow runs. We have only the Contact Us right now, so select this one. And using that event you can say send an email to the site admins if the form submission was successful. The whole repository and this module have great documentation where you can read more about these scripts and how to customize your VueForm content items. And don't forget to check out the recording of this demo on YouTube! News from the community Using the OrchardCore OpenID management feature with an existing OpenIddict deployment Kévin Chalet is one of the main contributors of Orchard Core. He developed the OpenID management feature for Orchard Core. In his blog post, he writes about how you can use the GUI of Orchard Core with an existing OpenIddict server, that is typically located in another project. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 163 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!

Media Profiles, Renamed SummaryAdmin shapes - This week in Orchard (16/10/2020)

Media profiles feature to Orchard Core that allows you to defined preset image resizing and formatting commands! Renamed SummaryAdmin shapes, and new routes to avoid features URL blocking by IIS, and a lot more in our current post! Orchard Core updates Prevent disabling or removing administrator role Let's say you set up your Orchard Core site using the admin as the user name and for some reason, you navigate to Security -> Users to disable your own account. The problem here is that in this case, you are the only user with an Administrator role in the system. From now you can't do that, you will get a warning message saying you cannot disable the only administrator. Go back and edit your own user again and try to edit the user name too. This also triggers a new validation error, because you cannot modify the user name of the currently logged-in user. The last thing here is about removing the Administrator role from your user account. You could do that, but if your user is the only user with the Administrator role assigned, you will get a warning message about you cannot remove the Administrator role from the only administrator. Avoid features URL blocking by IIS IIS has some default filters for security like you can't have specific words in the URL. There are a few words used by us too like .sitemap. IIS also blocks any request ending in .resources by default. The list of blocked extensions includes a bunch of other terms that could conceivably be used in feature IDs such as .master, .browser, .config, .skin, etc. It's possible to override this behavior in the web.config file but this would have to be done on a per-application basis and carries unwanted security implications. The solution is just to put these parts in a different segment. If you want to enable a feature the URL to do that was:https://localhost:5501/Admin/Features/Enable/OrchardCore.Sitemaps Now the new URL is:https://localhost:44300/Admin/Features/OrchardCore.Sitemaps/Enable So the goal of this fix is to use the pattern Admin/Features/{id}/Enable in place of Admin/Features/Enable/{id}. The same goes for when you want to disable a feature. Renamed SummaryAdmin shapes of ContentsDriver These shape names are not compatible when defining custom placement, so they have been renamed. They are admin shapes, so the impact is quite low. If you have your own custom theme and redefined these ones you have to change them. So, the ContentsDriver creates four shapes with different shape types. Shape("Contents_SummaryAdmin__Tags", new ContentItemViewModel(model)).Location("SummaryAdmin", "Tags:10"), Shape("Contents_SummaryAdmin__Meta", new ContentItemViewModel(model)).Location("SummaryAdmin", "Meta:20"), Shape("Contents_SummaryAdmin__Button__Edit", new ContentItemViewModel(model)).Location("SummaryAdmin", "Actions:10"), Shape("Contents_SummaryAdmin__Button__Actions", new ContentItemViewModel(model)).Location("SummaryAdmin", "ActionsMenu:10") However, the actual shape type is considered before __ i.e. all the above shapes are resolved to the same shape type Contents_SummaryAdmin. Renamed these shapes as following to apply a unique placement record for each shape. Contents_SummaryAdmin__Tags renamed to ContentsTags_SummaryAdminContents_SummaryAdmin__Meta renamed to ContentsMeta_SummaryAdminContents_SummaryAdmin__Button__Edit renamed to ContentsButtonEdit_SummaryAdminContents_SummaryAdmin__Button__Actions renamed to ContentsButtonActions_SummaryAdmin So that placement will target a single shape type. { "ContentsButtonActions_SummaryAdmin": [ { "shape":"ContentsButtonEditNoView_SummaryAdmin" } ] } Demos New ImageSharp.Web Features ImageSharp is a new, fully-featured, fully managed, cross-platform, 2D graphics library. Designed to simplify image processing, ImageSharp brings you an incredibly powerful yet beautifully simple API. With the v1.0., ImageSharp has got a bunch of new features and it's now a lot faster. And Orchard Core is also using ImageSharp to work with images. New features included: Format support to the Tag Helpers/Liquid Filters: The slight weirdness with adding this is the file extension on the URL will remain .png, but the image will be returned with the correct mime/type. Quality support to jpg encoding and Tag Helpers/Liquid Filters: The Quality support allows you to specify a quality % to jpg encoding. Note: only jpg encoding is supported, but the Format support allows you to convert an image from saying png to jpg, and then reduce the quality. CurrentCulture/InvariantCulture for query string parameters: Supported through custom ImageSharp configuration, but not integrated into Orchard Core. Basing this decision primarily on the idea that most of our resizing/processing query string building, is done through templates, which are culture invariant. And that's not all of it! There is now a new Media profiles feature in Orchard Core that allowing you to specify resizing options and much other stuff. A profile can then be called with the profile name resize_url: profile: 'banner' rather than having to specify all the resizing options that may apply. But that's enough talk for now, let's see them in action, after all, we are in the Demos section of This week in Orchard, right? Use the latest nightly build of Orchard Core and set up your site using the Agency recipe. Then navigate to the admin UI where you will see a new option in the menu (make sure to enable the Media profiles feature): Configuration -> Media -> Media Profiles. Media Profiles are quite simple, they just have the standard resizing options that we have in ImageSharp. Notice that here you can set the width and the height values only from the supported ones. We add the name md to this media profile, let's note it, we will need it right away. Now navigate to Design -> Templates and edit the predefined Content__LandingPage Liquid template. We will use the newly created image profile when displaying the portfolio images. Just a note here: the home page in this agency is a LandingPage content type that has several Bag Parts attached. The one with the display name Portfolio is about to add Project content types to your LandingPage content type. And the Project content type has a Media Field attached, called Image. In this Liquid template, we will use our newly created md media profile. Here we say use the md media profile when displaying these images and in this particular case we would like to override the resize mode for the processed image. Instead of crop, we would like to stretch these images, but just in this case. When you define a media profile, you can say I don't want to specify the width, the height or the resize mode. In that case, you can set them in your Liquid helper, just as you could do that before. Now, let's just check out how does the home page of our site looks like. Remember that we set a lot of values when setting up our md media profile and we also set the quality percentage for the processed image and we set it as 10. We also change the width and height values and override the resize mode to stretch the images. This result is low quality stretched images in the Portfolio section. Now let's see the source code of this page and check out the img tags using the DevTools of Chrome. As you can see it's not tied to ImageSharp, the logic just converts the media profile into a good query string. This means we can do the override easier and if we change the values the URL will change, and it breaks the cache. When you would like to show the kittens.jpg with 100 width and 100 height, by using the crop resize mode (that resizes the image using the same functionality as max then removes any image area falling outside the bounds of its container) and use only 50% as the quality when compressing the image you would write a Liquid filter like this: {{ 'animals/kittens.jpg' | asset_url | resize_url: width:100, height:240, mode:'crop', quality: 50, format:'jpg' }} The documentation is also updated to help you how to use these new arguments. Don't forget to head to YouTube and watch the recording of this awesome feature! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 162 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, YesSql improvements - This week in Orchard (09/10/2020)

Get ready for the upcoming additions of Orchard Core! This week you can see demos about adding distributed cache to Orchard Core and the latest improvements of YesSql! Orchard Core updates Restrict Content Types Admin Node to only create the specified content type Let's say you have a site set up with the Blog recipe and your goal is to add a new admin menu that is about to list all the existing Article content items. To do that you have to navigate to Configuration -> Admin Menu and click on the Add Node button. Here you will need to select the Content Types Admin Node because you would like to add a link for each one of the selected content types from the list. And yes, you will only select the Article content type in the next screen. And that's it, you have created a new admin menu that lists all of the Article content items from the system. If you click on that you will see the list of the Article content items. Note that from now you will not see a filter here to filter by content types because that really doesn't make much sense. You created this Content Types Admin Node to list only the Article content items. If you would like to filter by content type, use the filter in the Content -> Content Items page as you would do it before. Remove ManageOwnMedia permission The ManageOwnMedia permission isn't handled today and we can replace it with the ManageMedia permission. So, now there is no separate permission to manage their own media or manage the media. It will be added back to the system again if the authorization logic is to be able to separate the user's media and the media uploaded by others. Right now, if you head to Security -> Roles and hit the Edit button near one of the Roles, you will see the missing Manage Own Media permission. Use a dropdown menu on the admin top navbar for the user menu The user menu on the admin theme is just about listing the user name of the currently logged-in user with a little icon near it. And there was a Log off link at the right side of the user name. It was just a piece of HTML code in the Layout.cshtml file of the default admin theme. From now the whole user menu gets its own shape, called UserMenu.cshtml. If you would like to override the user menu, you don't need to create a Layout.cshtml file in your admin theme, you just need to override the UserMenu.cshtml file. And if you check out this GIF, you will see that now the content of the user menu is placed in a dropdown instead of having it's content inline. Document release procedure Orchard Core is open-source that means you can check out and request changes to the source code, tell your opinion about it, and update the relevant documentation for that piece of code. Now there is a new page in the Orchard Core Documentation about how to publish a new Orchard Core release. These notes are primarily for Orchard's core contributors to guide them on how to prepare a new release, but if you just take a look at these you can now see what are the steps that need to be done to be able to ship a new release of Orchard Core. Add option to allow Lucene query syntax in the search There is a setting in the Lucene module that you can turn on and whatever you type in the search box won't be parsed as 'these are the words that I need to search on', but parsed as this is a Lucene query. You can use the Lucene query syntax in search forms, like the quotes, plus signs and things like this. But by default, it will still be like today, which is type words and it looks for these words. If you type stuff that has weird characters, they would be ignored. But how can I turn on that feature? Just navigate to the admin UI of Orchard Core, then find the settings in Search -> Settings -> Search (make sure you have enabled the Lucene module). Demos YesSql: Adding support for multi filters on the same table index There is a new method on .IQuery called .Or(), which starts a filter on a distinct table. This can be used for instance when the same index needs to be queried for multiple sets. It will actually add many filters on the same record of the index. With .Or() you can do now filters on different inner joins of the same index. Which means it will do unions of result with the filters. Let's check out the following unit test. [Fact]public async Task ShouldQueryMultipleIndexes(){ // We should be able to query documents on multiple rows in an index. // This mean the same Index table needs to be JOINed. _store.RegisterIndexes<PersonIdentitiesIndexProvider>(); using (var session = _store.CreateSession()) { var hanselman = new Person { Firstname = "Scott", Lastname = "Hanselman" }; var guthrie = new Person { Firstname = "Scott", Lastname = "Guthrie" }; session.Save(hanselman); session.Save(guthrie); } using (var session = _store.CreateSession()) { Assert.Equal(2, await session.Query<Person>() .With<PersonIdentity>(x => x.Identity == "Hanselman") .Or() .With<PersonIdentity>(x => x.Identity == "Guthrie")) .CountAsync()); }} This PersonIdentitiesIndexProvider will just map the first name and the last name of each person. We created two persons here that means the provider will be creating four PersonIdentity records. Two to store the first name and last name for Scott Hanselman and two to store the first name and the last name of Scott Guthrie. If without using the .Or() it will issue a query where the Identity == "Hanselman" AND Identity == "Guthrie", which will return nothing. With the .Or(), it will do an inner join on PersonIdentity with a filter on Identity == "Hanselman" and another inner join on PersonIdentity with a filter on Identity == "Guthrie". In this case, we will get both the two persons. It's like give me any person who's PersonIdentity has a record like Hanselman OR where the PersonIdentity equals Guthrie. Let's see another example! // Creating articles.using (var session = store.CreateSession()){ session.Save(new Article { Content = "This is a green fox" }); session.Save(new Article { Content = "This is a yellow cat" }); session.Save(new Article { Content = "This is a pink elephant" }); session.Save(new Article { Content = "This is a green tiger" });}using (var session = store.CreateSession()){ Console.WriteLine("Boolean query: 'pink or tiger'"); var boolQuery = await session.Query<Article>() .Where(x => x.Word.IsIn(new[] { "pink" })) .Or() .Where(x => x.Word.IsIn(new[] { "tiger" })) .ListAsync();} This is a full-text sample where in this case we can query documents by their content, by their words. If we have the documents as you could see in the code, we are creating an index for all the words pointing to the document, like green and fox points to the first Article. Now the query is about to give me all the documents that have pink in it OR all the documents that have tiger in it. The goal is to get the last two articles in this case. Let's check out this query: var boolQuery = await session.Query<Article, ArticleByWord>().Where(a => a.Word.IsIn(new[] { "white", "fox", "pink" })).ListAsync(); This query will return all the articles that have white AND fox AND pink in it and there is none in this case. You can find the recording of this improvement on YouTube! But wait a minute! Could this syntax be better? When you have a query, you can say .Any() and every predicate will be done in a different table. .Any() being an OR, and .All() being an AND. In this case, we're querying on the same index (ArticleByWord) but each of the calls on .With() will be a different projection, a different inner join in this case. Here we are looking for an article that has the word pink OR the words green AND fox. await session.Query<Article>() .Any( x => x.With<ArticleByWord>(a => a.Word == "pink"), x => x.All( x => x.With<ArticleByWord>(a => a.Word == "green"), x => x.With<ArticleByWord>(a => a.Word == "fox"))).ListAsync(); SELECT DISTINCT Document.* FROM DocumentINNER JOIN ArticleByWord_Document AS [ArticleByWord_Document_a1] ON ArticleByWord_Document_a1.DocumentId = Document.IdINNER JOIN ArticleByWord AS [ArticleByWord_a1] ON [ArticleByWord_a1].Id = ArticleByWord_Document_a1.ArticleByWordIdINNER JOIN ArticleByWord_Document AS [ArticleByWord_Document_a2] ON ArticleByWord_Document_a2.DocumentId = Document.IdINNER JOIN ArticleByWord AS [ArticleByWord_a2] ON [ArticleByWord_a2].Id = ArticleByWord_Document_a2.ArticleByWordIdINNER JOIN ArticleByWord_Document AS [ArticleByWord_Document_a3] ON ArticleByWord_Document_a3.DocumentId = Document.IdINNER JOIN ArticleByWord AS [ArticleByWord_a3] ON [ArticleByWord_a3].Id = ArticleByWord_Document_a3.ArticleByWordIdWHERE ArticleByWord_a1.Word = 'pink' OR ( ArticleByWord_a2.Word = 'green' AND ArticleByWord_a3.Word = 'fox') Here you can also see how does the query look like. That's the current syntax right now. And it's not breaking change because if you had .query.With().With(), it will still behave the same as before. It will be a single projection with two .With(). If you project on the same table it will be an AND on the same table, the same projection.If you would like to know more about the current syntax and the latest features, this is the YouTube video that you are looking for! Distributed Redis Cache There is a huge PR with a great addition to Orchard Core about having Distributed Cache in Orchard Core. In fact, this PR is related to all modules services using cached data that need to be in sync with a shared database, e.g. site settings and other admin settings, templates, queries, layers, and so on. Currently, in the dev branch, this is already the case for most of them but by using local memory cache entries that are invalidated through a distributed signal. This PR has changed this pattern by using a multi-level cache including a distributed cache. And Jean-Thierry Kéchichian made more services to be distributed aware, there are remaining things but could be done in other PRs. And recently he added the ability through a separate feature to also keep in sync tenant states, when you enable/disable/create/setup a tenant. To summarize: All services that were using the memory cache are now using a multi-level cache including a distributed cache, this cache is kept in sync with the database without using a message bus but document identifiers. We have concrete implementations of distributed services based on Redis, Redis cache, Redis data protection, Redis message bus, and Redis lock. In the current code, we never use a message bus/distributed lock. When enabling a concrete distributed cache in the default tenant, we automatically keep all tenants in sync through a hosted service, here also without using a message bus but identifiers. Here a stateless configuration is needed. There is a separate feature (DefaultTenantOnly) to keep tenants in sync. Don't forget to head to YouTube and watch the recording of this upcoming feature! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 160 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!

New custom filters in Fluid, Media options admin page - This week in Orchard (02/10/2020)

We prepared two interesting demos for this week: The first one is about having new useful custom filters in Liquid to make formatting numbers and string easier. The other upcoming feature is about how you can show your settings from your appsettings.json files without having the need to open these files in your file system. Orchard Core updates Restrict Content Type Admin Menus to only create the specified Content Type Several issues fixed regarding creating content items from the admin UI: Restored the new button specific to each content item when user filters by content type or accesses the content item list interface by link for a single content type in the admin menu. Fixed the behavior of the admin menu's links to Menus and Content Items: if they are not defined inside a recipe, they have a dynamic behavior and it causes an issue if the user defines a link for a specific content type inside the admin menu. In the BlogTheme, the Content Items link of the admin menu is defined in the recipe and doesn't have dynamic behavior. See the following GIF here where you can also see the creation of a new content type admin menu node that is about to list the Article content items. The new button under the new Article menu option is just about to create new Article content items. Update Blob Storage to search folder hierarchies The problem is that the method that is responsible to handle Blob Storage items does not correctly implement the includeSubDirectories = true option - it never did. This is because it's not like a normal file system where you can make one request and list everything, so it would have to make recursive requests for every directory it finds. Ironically the media step driver does this recursion already itself, but the recipe step does not when using Include All Media. So the short term workaround should be to specify the attached fields' folder's media fields, rather than Include All Media when creating the step. This issue withincludeSubDirectories = true affects this step, and the GraphQL media query - it's the only place we use it. So, Blob storage never handled searching subfolders correctly, so this should now work for the media step, and better in GraphQL queries (behaves identically to normal file system now). Now if you would like to get the content of the directory including subfolders too, the GetDirectoryContentFlatAsync method in the BlobFileStore class will return the files inside the subfolders too. Rename Smtp admin menu to Email The goal of renaming Smtp to Email is to make sure that you can edit settings related to sending emails even if you don't know what SMTP is (and this screen is also for testing email sending). Toggle password visibility on the login form and on the setup screen The login form and the setup screen now support toggling the password visibility, so can make sure that you typed the correct passwords in these textboxes. Demos Media options admin page In the appsettings.json file, you can define your media-related settings, e.g. change the list of allowed file extensions or the path used when serving media assets. The documentation includes all the default configuration values that can be overridden. The goal of this feature is to have a read-only version of the settings where you can see these configuration values without needing to navigate to your appsettings.json file to see the configured values. Head to YouTube to check out this short recording about this upcoming feature! New custom filters in Fluid Fluid is an open-source .NET templating engine that is as close as possible to the Liquid template language. It's a secure template language that is also very accessible for non-programmer audiences. It also contains an ASP.NET Core MVC View Engine. And of course, Orchard Core is using Fluid too to generate templates. If you would like to render numbers correctly, Fluid just renders them in a format 124456789, but you could not format it like for example 12,445.68 )(and you can't do it in Liquid by default either). We already had the format_date helper in Fluid where we can use the .NET formats, so the new helpers added are format_number and format_string, which are using the .NET format methods. They are not standard in Liquid, but there is nothing in Liquid to help achieving these. format_number: It will format the number with the current culture. If you pass "N", which means number in the standard numeric format strings, then it will use the number format that we have just mentioned above. So, to generate 12,445.68 from the 12445.6789 value, you can do that like 12445.6789 | format_number: "N" You can find a documentation about the standard numeric format strings here. format_string: In this case, you can pass a string with a String.Format inside and after using the format_string you can pass the values. Let's say you have the following expression: "hello {0} {1:C}" | format_string: "world" 123. This would be rendered as hello world $123.00. Notice that here we also used the currency ("C") format specifier to convert a number to a string that represents a currency amount. The documentation of Fluid contains the available custom filters where you can learn more about the other features of Fluid too. Head to YouTube to check out the recording about the new custom filters! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 161 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!