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

Help shape Orchard Core's new website, a new website using Orchard Core - This week in Orchard (17/07/2026)

When you add a custom settings page, does it look like it belongs in the admin UI?

When you utilize workflow activities, does JavaScript syntax have to be the only option?

After checking out this week's Orchard news, both have better answers.

Thanks to Mike Alhayek, admin forms across settings and configuration pages now use the same ocat-* CSS class conventions, replacing legacy Bootstrap and Orchard-specific helpers. And all workflow tasks that previously only supported JavaScript now also support Liquid, with a new LiquidTask added to match ScriptTask.

Also this week: Nick Jackson's Orchard Core website redesign is open for community feedback, and GoRide joins the showcase of sites running on Orchard Core.

Read on for the details, or jump to the section that matters to you!

Latest tutorials

Featured tags

AI
SMS
IIS
MCP
API
SEO
SSL
All tags >

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!

Generic Site Settings Deployment Step, Extensible filters for contents admin list - This week in Orchard (17/07/2020)

The community has just released RC 2 a few weeks ago, but ever since Orchard Core has got several new features. This week among others we are going to see the extensible filters for contents admin list and the generic site settings deployment step. Orchard Core updates New column to the media library table view Enter the dashboard of your Orchard Core site and navigate to Content -> Media Library. Here you can view the uploaded files in a list view and in a grid view. You can switch between them using the little icons on the left side of the Filter textbox. If you view the files using the list view you will see a new column called LastModify. You can also sort the items by clicking on the header of the LastModify column. Extensible filters for contents admin list You can extend what filters are available in the contents admin list and each module can provide their own filters. Let's see this feature closely! First, install your site using the Blog recipe. Now, head to Configuration -> Features and enable the Taxonomies Contents List Filters and the Content Localization modules. The Content Localization is about to provide a part that allows localizing content items. The Taxonomies Contents List Filters feature is adding a new option under Configuration -> Settings -> Taxonomy Filters where you can select the taxonomies to filters in the contents list. As you can see, the Blog recipe comes with two predefined taxonomies: Tags and Categories. Let's select both ones. Now, head to Content -> Content Items, where you could see three new drop-downs. Categories and Tags can be used to filter by the values of the Category and the Tag Term content type. Just for the sake of demonstration make the Blog Post content type listable to see the Blog Post content items in the content items list. After if you select to filter for the content items that have the Earth tag, you will see the default one, because that post has each of these three existing posts. And you can easily add your own filters for the content items list! Without going into the details you have to add a new driver by implementing the DisplayDriver<ContentOptionsViewModel> abstract class and implement the IContentsAdminListFilter interface where you can provide the logic for filtering - modify the query (IQuery<ContentItem>) - content items. Check the TaxonomyContentsAdminListDisplayDriver.cs and the TaxonomyContentsAdminListFilter.cs files to see good examples about how to create your own filters. There was a demo about the new content filters and in the case, if you haven't seen it yet, you can watch the recording here. Demo videos in docs From time to time, the members of the community will do demos to show the latest features and improvements of the CMS. These videos are very helpful if you would like to learn a given topic (for example how to create Custom Settings using the admin UI) and you prefer videos. Now every topic in the documentation of Orchard Core containing the recording that is about showing you how to use the given feature. If we stay at the same example we will see the video at the bottom of the Custom Settings page. Add and implement IsJson() string extension method We are sure that you will meet some code in the future that is using JSON in their editor templates and you want to/need to validate that the text supplied in the editor is valid JSON. Now you can find a string extension method called IsJson() in the OrchardCore.Mvc.Utilities classes to do this. Demos Generic Site Settings Deployment Step When you navigate to the GitHub page of Orchard Core and list the open issues you will find one that is about listing the missing deployment steps, which means some settings do not have a deployment step to import and export them. The goal here is to be able to import/export every setting. For that, we have to get familiar with the notion of Generic Site Settings Deployment Step. You will find a new class library called OrchardCore.Settings.Core, where is a folder named Deployment that is containing logic to add site settings to a DeploymentPlanResult, a generic display driver that is responsible for the UI of the deployment plan and many more. Feel free to discover the content of this project! Now let's jump to the OrchardCore.Admin module. If you want to handle the custom settings via the OrchardCore.Settings.Core library, don't forget to reference it in your project. If you do that you can easily import/export the settings in your deployment plan. There is a class called AdminSettings in the OrchardCore.Admin module that contains one DisplayMenuFilter boolean property. Let's make it importable/exportable! Head to the Startup.cs file of the module and check out the DeploymentStartup class of it. Here you can see how you can use the provided generic business logic from the OrchardCore.Settings.Core project. You can see that we created a new deployment plan with the name: Admin settings and the description: Exports the admin settings by just passing these localized strings to the SiteSettingsPropertyDeploymentStepDriver. That's an easy and generic way to implement a deployment plan for your settings in your module! If you would like to know more about the generic site settings deployment step, head to YouTube! News from the community Intensive Orchard Core training for the In Motion team We had the opportunity to provide a five-day intensive Orchard Core training for the In Motion team! Read our post to know more details about the training! Orchard Core workshops The contributors of Orchard Core will hold some unique online workshops in September 2020. So even with Orchard Harvest postponed due to the coronavirus pandemic we'll get some new learning events. Are you looking to get up to speed with Orchard? Check out the workshops' details on the Orchard Core homepage! Orchard Dojo Newsletter Now we have 152 subscribers of the Lombiq's Orchard Dojo Newsletter! 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!

Content Picker Menu Item, Kast case study - This week in Orchard (02/05/2020)

Soon you will able to show content items in your menu easily! How? Check our newest This week in Orchard post and read about an amazing demo to see the new Content Picker Menu Item in action! We published a brand new case study this week on our website about the latest Orchard Core site we developed. By reading that study you can see the possibilities that you can easily achieve by using Orchard Core as your CMS! Don't forget to read our whole post for the most interesting news around the community! Orchard Core updates Added ability to restrict widgets within a flow part You can use the FlowPartSettings to give content managers the capability to restrict which widgets are available within the flow editor. If no widgets have been selected then all widgets will be available, as per the current implementation. Let's see it quickly! Set up a site with the Blog recipe and then edit the content type definition of the Page content type. To do that navigate to Content -> Content Definition -> Content Types and choose the Page. Then find the attached parts and hit Edit near the Flow one. Here you can select which content types this flow can contain. Just for the sake of demonstration, we say that the Flow editor of this page can only accept Liquid widgets. Let's see what will happen when we create a new Page! Hit New -> Page and try to add something to the Flow editor. You will see that only the Liquid one will be on the list because in the previous step we only allowed Liquid widgets. So, when you attach a FlowPart now you can decide what content types you want to be able to use in a FlowPart. It can be useful if you create a form page type with a FlowPart for it. You could then decide just to allow for form widgets. Remember: if you don't select anything you will be able to use any type of content type with the Widget stereotype in your editor. Added support for IN (SELECT) SQL statements You can use a custom SQL statement, that is about to parse for the queries module, the one that uses the generic SQL language and that will be translated to any dialect that the CMS supports (PostgreSQL, MySQL, SQLite, Microsoft SQL Server). If you use this language now you can use the select expression inside an in statement. It's also supporting the not in correctly and the like and not like was not working well, so these are also fixed. Check the new InlineData attributes added to the ShouldParseExpression test method to see some examples with the new expression. Fix shape table providers There was an issue with the way you would be able to override a template from your module, override a template for a dependent module. This change will look for shape templates in a module for any first-level dependencies and it's also improving performance because there would be fewer shape templates loaded in the memory. And if you have a feature depending on another feature then it won't be able to override the second level feature, you have to depend on that. It makes sense because you are creating a template for the second level feature, so you can depend on that because you expected that it would be there. Deployment plans search Let's navigate to Configuration -> Import/Export and create one or more deployment plans. Here you can filter the deployment plans and also do bulk actions. To do bulk actions select two or more deployment plans and after that, you will see the Delete option in the Actions dropdown. Content culture picker shape documentation If you navigate to the Content Localization section in the Orchard Core documentation, you may have noticed that there were no Razor example codes. From now the documentation has been improved with Razor examples! Demos Content Picker Menu Item Let's set up a site with the Blog recipe, create a new Page, and call it My brand new page. Then choose the Main Menu option in the admin UI and hit the Add Menu Item button. Here you could see the Available Menu Items modal window with two options: Link Menu Item and Content Picker Menu Item. Let's choose the second one! The Content Picker Menu Item is about having the ability to choose from the content items available in the CMS with a content picker. There is the Selected ContentItem dropdown, that can be used to select the content item that you would like to show on the menu. You can type to search or just simply select your item from the list. We will select our newly created page here. Publish the menu and navigate to the homepage of your site to see your menu. We placed the new menu item after the About, but of course, it's your choice to set the position of your menu item. If you are interested in the full demo don't forget to watch the recording on YouTube! Note that this feature is under development and can be found in this branch! News from the community Orchard Nuggets: How to add a culture URL segment for localization in Orchard Core So you're building a localized Orchard Core site and want all URLs to be in the form of /culture-name/rest/of/the/url, e.g. /hu-HU/my-page. What do you need to achieve this? In our newest Orchard Nuggets post, we give you the answers! Check out the other posts for more such bite-sized Orchard tips and let us know if you'd have another question! Helping Kast build a multi-tenant platform on Orchard Core Kast is an Australian company and one of their primary goals is to implement the Kast platform with the Kast Group Finder component. We worked together with Seth Cleaver (Co-founder and Director of Kast) on this tool to be able to create an intuitive self-service process that enables people within a church to easily find a suitable group to attend, simplify the administrative processes required for getting people into groups, and provide information to the group co-ordinators that might assist in planning and measuring effectiveness. Check out this case study about how we've developed this multi-tenant social group management platform for churches! 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. Orchard Core Training Demo module: combining ASP.NET Core Options with Orchard Core site settings Our Orchard Core Training Demo module has a new tutorial on combining ASP.NET Core Options with Orchard Core site settings. In the SiteSettingsController you could see how to use the Site Settings to access tenant-level settings and any other custom settings! Orchard Core Training Demo module is a demo Orchard Core module for training purposes guiding you to become an Orchard developer. You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core NuGet packages, however, it's harder to look under the hood of Orchard Core features. The module assumes that you have a good understanding of basic Orchard concepts and that you can get around the Orchard admin area (the official documentation may help you with that). You should also be familiar with how to use Visual Studio and write C#, as well as the concepts of ASP.NET Core MVC. Bug reports, feature requests, and comments are warmly welcome, please do so via GitHub. Feel free to send pull requests too, no matter which source repository you choose for this purpose. Updated Lombiq Technologies logos You may have noticed that we rolled out our updated logo in the last few days. The spirit is the same: The lab flask with which we distill our IT solutions ("lombik" in Hungarian means lab flask :)). So, please welcome it! Orchard Core workshops The contributors of Orchard Core will hold some unique online workshops in the coming months, between May and September 2020. So even with Orchard Harvest postponed due to the coronavirus pandemic we'll get some new learning events. Lombiq's developers will also give two workshops, on using Orchard from the admin UI and on developing a module. Are you looking to get up to speed with Orchard? Check out the workshops' details on the Orchard Core homepage! Orchard Dojo Newsletter Now we have 140 subscribers of the Lombiq's Orchard Dojo Newsletter! 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!

Error Log Watcher in Lombiq Orchard Visual Studio Extension, Disable and Enable Tasks - This week in Orchard (03/04/2020)

New tasks when working tenants in your workflows, a best practice about how to validate your ViewModel using a service and a spectacular and fun demo about a nice addition to our Orchard Visual Studio Extension! Read our current post for more! Orchard Core updates Tenant Workflows: Disable and Enable Tasks Now you have workflow tasks to Disable or Enable tenants to support tenant management using with Forms or any external services. With these you have four events to manipulate tenants: Create Tenant Enable Tenant Disable Tenant Setup Tenant From now, you can use the workflows to create, setup and then enable the tenants, because we have tasks to cover the whole process. In our case, we created a workflow called Add tenant and used these activities to fire up a tenant from scratch by the values provided by the users in a form. Search inputs Antoine Griffard updated all the search inputs in admin to use autofocus and type="search". This is a way to let the browser display these inputs with better hints. You can even predefine a list of common search inputs if you want. It's not used here, but we could also extend these to do that or show a list of historical data that you put in that textbox. Validating ViewModels We would like to mention this because by reading this solution you could get a nice best practice about how to validate something with a service if you are in a ViewModel. In this current issue, we would like to validate the value of an email address by using the RegisterExternalLoginViewModel. If you would like to validate an object using a ViewModel, you have to implement the IValidatableObject interface which will give you a Validate method. And in this method, you can use whatever service you want. When you create a new instance of your ViewModel, you can pass your service to it in a parameter by using constructor dependency injection. In this current example, we could see the passing of the IEmailAddressValidator to the RegisterExternalLoginViewModel. And in the RegisterExternalLoginViewModel you can use the service in the Validate method injected using the constructor. But, if you see the changes below, you could notice that by using the ValidationContext, you can get your service from the IServiceProvider by calling validationContext.GetService<T>(). In this case, you don't have to pass anything using the constructor when creating a new instance of your ViewModel, just simply resolve your service using the ValidationContext. A new section in the Orchard Core documentation: Resources Now when you open the documentation of Orchard Core, you will find a new item on the menu, called Resources. The goal of the Resources page is to collect any external resources that are available to teach you how to develop with Orchard Core. Our Orchard Core Training Demo module has been added as the first demo project for this page. And you can also found some lines about our newsletter here and the URL where you can sign up for our newsletter! New favicon for the Orchard Core documentation If you check the previous screen again, you will see that the snip contains the title bar of the window too. That's because when you visit the documentation page of Orchard Core, you will face a new blueish favicon, that looks nicer in a browser that uses a darker theme too. Demos Adding BlinkStick support to Lombiq Orchard Visual Studio Extension Orchard Error Log Watcher feature Lombiq Orchard Visual Studio Extension is a Visual Studio extension with many features and templates frequently used by Lombiq developers. It contains Orchard-related (including Orchard Core) as well as generic goodies. This extension has an Orchard Log Watcher feature, that alerts you when you have any new entry in the log file. When you install this extension, you will see a new button on the Orchard Log Watcher toolbar. The button of this toolbar will be enabled when you have unread entries in the error log files. If you click on this button, the log file will be opened with the editor assigned to open .log files. When you navigate to Tools -> Options -> Lombiq Orchard Visual Studio Extension -> Orchard Log Watcher you can enable or disable this feature. You can also set the log file folder path. The path can be anything, so, you can set custom paths as well. The default path here supports the default path of the log files in the case of an Orchard Core and an Orchard 1.x solution too. And here comes the fun part: you can also set to blink or light up continuously a BlinkStick LED stick when a new entry is detected. BlinkStick brings colorful notifications to your computer and wide range programming language implementations give you the power to control LEDs without the need to program a microcontroller and you can choose from different kinds of products. Furthermore, you can also set the color for the LED by providing a hex value or the name of the color. You can find the list of the supported colors here. You just need to plug this device into your USB port and the extension will recognize it! Here you can download this free, open-source extension. In GitHub, you can find the extension's Readme with release notes too. Also, if you encountered bugs or have a feature request please add it on the GitHub page as well. And don't forget to watch the full demo on YouTube! News from the community Training Demo updated: how to add an ASP.NET Core middleware to your Orchard Core application? Orchard Core Training Demo module is a demo Orchard Core module for training purposes guiding you to become an Orchard developer. You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core NuGet packages, however, it's harder to look under the hood of Orchard Core features. The module assumes that you have a good understanding of basic Orchard concepts and that you can get around the Orchard admin area (the official documentation may help you with that). You should also be familiar with how to use Visual Studio and write C#, as well as the concepts of ASP.NET Core MVC. We have just added a new section to our module about how to implement an ASP.NET Core middleware in your Orchard Core application. Take a look at the RequestLoggingMiddleware.cs file! Orchard Dojo Newsletter Now we have 130 subscribers of the Lombiq's Orchard Dojo Newsletter! 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 disabled/enabled events, filter admin menu - This week in Orchard (07/02/2020)

Orchard Core has got several new features and fixes this week! With many others, we will see the new user disabled/enabled events, the new IAreaControllerRouteMapper implementation, the way how you can filter the admin menu then show you a demo about how to integrate stripe.js in your Orchard Core application with workflows. And finally, say some words about a new tentative date and location for the upcoming Harvest! Orchard Core updates Reduce the length of indexes for Content Fields Indexing Let's focus on the LinkFieldIndex and check these two columns: the Url and the BigUrl. The Url is the one that is trimmed and indexed, and the BigUrl is the original data that is not indexed. If you are using MySQL, the maximum length that this provider can support in an index under UTF8 collection is 768. Now we set the maximum length of the indexed columns is to not be longer than the supported length. Do not check "Include all content types" in deployment step by default When you create a content type deployment step, the default is to export all types. Now, this is unchecked by default. Adding User Disabled/Enabled Events The IUserCreatedEventHandler is changed to IUserEventHandler and there are two new events: DisabledAsync and EnabledAsync events. These two new events now triggered in the UserDisplayDriver that will trigger the two newly created workflow events to make it work in your workflows. Adding IAreaControllerRouteMapper Now there is an updated way how the admin prefix is applied by using custom convention and constraint that will ensure that the admin URLs start with the admin prefix. And also ensure that it is done correctly for the controllers that are named AdminController, not the ones that start with admin. Before every controller that starts with admin could be an admin controller, but now with this new convention, it has been decided that only controllers named AdminController can be an admin controller. For example, a controller named AdminItemController doesn't fall into this category, so it can't be an admin controller. A concrete implementation being AdminAreaControllerRouteMapper that uses AdminOptions to provide a default route pattern that is used in the OrchardCore.MVC startup. Just as a reminder, if you have admin controllers you have to name them AdminController or have the Admin attribute on that. This will ensure that the URL is strictly using the admin prefix (or whatever you set it), and the user has the admin permission and this will also apply the admin theme to the views from this controller. Filter admin menu Head to Configuration -> Settings -> Admin and put a tick near the Enable Admin Menu filter checkbox. Now you will have a new textbox at the top of the admin menu with a Filter placeholder text inside it. If you type something here you can filter the menu items and could find easier the option you want. And if you hit CTRL+SHIFT+F, this textbox will get the focus and you can type the menu option that you are looking for without needing to click into this textbox. Add menus content listing and create option If you navigate to the Content option of the admin menu you will find a new one, called Menus. This feature is listing all the menus of the system, and if you can see, there is a new button, called New Menu. By clicking on this button you can create a new Menu without needed the Menu content type to be creatable. Make lists sortable with ordering setting A few weeks ago we write about a way how you can make sortable lists using the Enable Ordering setting of the ListPart and you can also find a demo on YouTube about this feature. The good news is this feature is now merged to the dev branch of Orchard Core! Checkout to the latest changeset of the dev branch and try this feature now. Then don't forget to tell your opinion about it in the comments section! Razor Helpers documentation Now there is a new page in the Orchard Core documentation that contains the extension methods that are available in Razor using @Orchard. This documentation also contains the way how to use an extension method in a view and in a controller too. Demos Stripe.js and Workflows You can use Stripe.js’ APIs to tokenize customer information, collect sensitive card data using customizable Stripe Elements, and accept payments with browser payment APIs like Apple Pay and the Payment Request API. And of course, you can add Stripe.js to your Orchard Core site too! Let's create a registration form where users can register and after successful registration, they can pay the fee for a ticket. After the user submits the form, here comes a huge workflow, that will validate all the fields of the form. Here you can see the several validations, and when there is no error, the workflow will send an email, create an Enrollment in Orchard Core and redirect the user to stripe using a Fork. And there will be another workflow that will validate the payment using the response that Orchard Core will get from stripe.js. Now let's take a closer look at the Create Content Task that creates a new Enrollment content type. When you are creating a new content type using this task, you have to write the properties of the content. This is the JSON that is used to construct the given content item. As you can see, here you can use different Liquid expressions as well, for example, we could use the data coming from the form. You can see the website using this registration form under this URL. Here just click on the Register at the top right and select from the listed options. If you would like to see the whole demo just head to YouTube and watch the recording! News from the community A new tentative date and location for the next Harvest We have another tentative date for the next Harvest: the last week of June. In this date, we could do it in Europe and in a location that is easier to go from the USA too. London and Amsterdam have airports that can be reached easily from several other countries as well. What do you think about the new date and locations? Orchard Dojo Newsletter Now we have 114 subscribers of the Lombiq's Orchard Dojo Newsletter! 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!

This week in Orchard - 12/27/2019

New deployment step for Open ID Server, a new multi-tenant platform built with Orchard Core and a very interesting demo about a custom admin tree module with taxonomy terms menu are waiting for you among other exciting news in this year's last This week in Orchard post! On Orchard Core Allow replacing a Liquid filter Orchard Core has several built-in Liquid filters. You can make your own Liquid filter if you implement the ILiquidFilter interface. However, it could be a valid use case if you would like to change the behavior of one of the predefined built-in filters and replace it with your own one. When registering a Liquid Filter to the service container, you have to do it in the ConfigureServices method of your Startup.cs file: public override void ConfigureServices(IServiceCollection services){ services.AddLiquidFilter<BuildDisplayFilter>("shape_build_display"); services.AddLiquidFilter<ContentItemFilter>("content_item_id");} Here you can see how to register the shape_build_display and content_item_id filters. But let's have a closer look at that AddLiquidFilter extension method! public static IServiceCollection AddLiquidFilter<T>(this IServiceCollection services, string name) where T : class, ILiquidFilter{ services.Configure<LiquidOptions>(options => options.FilterRegistrations.Add(name, typeof(T))); services.AddScoped<T>(); return services;} You could see that every time when you call AddLiquidFilter it adds your filter to the FilterRegistrations Dictionary. To be able to override an existing Liquid filter with your own, Jean-Thierry Kéchichian had to change this extension method a little bit and instead of adding the new filter to this Dictionary, just overwrite an existing one. public static IServiceCollection AddLiquidFilter<T>(this IServiceCollection services, string name) where T : class, ILiquidFilter{ services.Configure<LiquidOptions>(options => options.FilterRegistrations[name] = typeof(T)); services.AddScoped<T>(); return services;} Delete role should warn the user if the role has associated users Let's create a custom role and let's name it Blogger. Now let's create a new user and add the Blogger role to it. Now go back to the Roles page and delete the Blogger role. If you hit the Delete button you will see a warning message, that says this role is associated to existing user(s). Prefix resource manager definitions for sample themes When you would like to register your resource using the ResourceManifest, you have to do something similar: manifest .DefineScript("vendor-bootstrap") .SetDependencies("vendor-jQuery") .SetUrl("~/TheBlogTheme/vendor/bootstrap/js/bootstrap.min.js", "~/TheBlogTheme/vendor/bootstrap/js/bootstrap.js") .SetCdn("https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js", "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.js") .SetCdnIntegrity("sha384-JjSmVgy...", "sha384-rkSXwmdF/9eRLkw/gNZG+1...") .SetVersion("4.3.1"); But what if you want to register Bootstrap again in your custom theme? You can do that of course, but when there are multiple resources with the same name, the resource manager takes the one with the highest version. // Use the highest version of all matchesif (resource == null || (resourceDefinition.Version != null && new Version(resource.Version) < version)){ resource = resourceDefinition;} To make things easier every predefined resource in the themes available in Orchard Core now has prefixes, which is the name of the theme. As you can see in the following code snippet, we registered the script for Bootstrap in the Blog theme with the name: TheBlogTheme-vendor-bootstrap. manifest .DefineScript("TheBlogTheme-vendor-bootstrap") .SetDependencies("TheBlogTheme-vendor-jQuery") .SetUrl("~/TheBlogTheme/vendor/bootstrap/js/bootstrap.min.js", "~/TheBlogTheme/vendor/bootstrap/js/bootstrap.js") .SetCdn("https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js", "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.js") .SetCdnIntegrity("sha384-JjSmV6OrQ6VrjIEaF...", "sha384-rkSGcqMuXXwmdF/9eRLkw/gNZG+1zYut...") .SetVersion("4.3.1"); Deployment step for Open ID Server Head to Configuration -> Features and enable the OpenID Authorization Server module. Then you will get a new OpenID Connect option under the Security menu, where you can set up the authorization server, application, and scopes. If you set up the server in a way (the way how it's not important right now) you can import the settings of your server if you create a new deployment plan under Configuration -> Import/Export -> Deployment Plans. If you select the OpenID Server step, that will export all the Open ID Server settings. Just execute the deployment plan locally. After if you open the Recipe.json file in the zip you will find a section called OpenIdServer in the steps section. "steps": [ { "name": "OpenIdServer", "OpenIdServer": { "AccessTokenFormat": 0, "Authority": null, "CertificateStoreLocation": null, "CertificateStoreName": null, "CertificateThumbprint": null, "AuthorizationEndpointPath": "/connect/authorize", "LogoutEndpointPath": "/connect/logout", "TokenEndpointPath": "/connect/token", "UserinfoEndpointPath": "/connect/userinfo", "GrantTypes": [ "authorization_code", "refresh_token" ], "UseRollingTokens": false } }] In the specific content type list only allow the creation of the new content item of the selected type In the admin page, you have a Content Types submenu under the Content menu, where you can list all of the content items. If you click on one of those (for example the Article) there was a green New button where you can create any type of content item that is creatable. Now with a new improvement, the UI responds to the type of the selected content type and (if the Content Type is marked as creatable) you can create only a new content item of the selected type. Here you could see the green button has a text: New Article. New multi-tenant Orchard Core platform GovBuilt has over 30 years of government software experience. They worked with government employees, contractors, and citizens to build a best-in-class online solution that streamlines the permitting and licensing process. They offer a GovBuilt Platform built for Government. And they are using Orchard Core to build their solution! They have several tenants, and https://pottcounty.govbuilt.com/ is one of that! Demos Custom Admin Tree module with taxonomy terms menu You can find a new module in this repository called ThisNetWorks.OrchardCore.AdminTree and a new theme here, called ThisNetWorks.OrchardCore.Themes. If you clone these repositories and add them to your Orchard Core solution you will see a new module under Configuration -> Fetaures called ThisNetWorks Admin Tree Menus. ThisNetWorks Admin Tree module displays content items based on a URL tree or taxonomy structure. This module presents a taxonomy and it's associated terms in a tree menu. The primary purpose of this menu is intended to provide a way to manage complex taxonomies, in combination with a navigation system that makes manages those terms, and content items easier. Let's enable this feature! Now go Design -> Themes and make the ThisNetWorks Admin Theme as the current theme. This adapts the default admin theme to support the menu's on the left sidebar to include clickable entries on tree nodes (i.e. nodes that contain child items can also contain a link to an entry). To be able to test the current capabilities of this solution quickly, you can use a recipe (Configuration -> Recipes) called Categories, that contains sample content items and taxonomy for a taxonomy menu tree. After you run this recipe you should see the following admin menu structure. Here you can see a Categories option with several sub-items. Categories is a taxonomy with the Category term content type and this admin menu shows you the structure of the Categories taxonomy in a clickable way. For example, if you select Motorbike, the site lists you all the content items that have this taxonomy and the category of that is Motorbike. If you click on the blue Create Leaf Article button you can create a content item that has a permalink and the Categories taxonomy will be set to Motorbike by default. Let's see what will happen if you click on the View button near the Articles content item, that is the root term content item of the Categories taxonomy. As you can see, users in the front-end can navigate between the different levels of terms and when navigating between the different content items, you can use different kinds of badges to show the terms and of course, the URL reflects this change as well. This feature is under development and we hope that this will be part of Orchard Core soon! If you are interested in this demo don't forget to check this video on YouTube! On Lombiq Orchard Dojo Newsletter Now we have 108 subscribers of the Lombiq's Orchard Dojo Newsletter! 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!