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

Featured tags

IIS
API
SMS
SEO
All tags >

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

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

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

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

Monaco Editor, Introduce ResourcePosition - This week in Orchard (13/03/2021)

The Monaco Editor is the code editor that powers VS Code. And from now you can use it in Orchard Core too! Check out our post for the latest improvements of Orchard Core and don't forget to take a look at our Orchard Ambassadors Toolbox! Orchard Core updates Add some comments to DataMigration class It can happen that you don't remember the correct syntax of the methods that you need to implement when you are adding your migration classes. It's useful to have it actually written down somewhere where you don't have to search. Now if you open up the DataMigration class in the OrchardCore.Data.Abstractions project you will find some comments about the correct syntax. Introduce ResourcePosition Imagine you have multiple resources (CSS or script files) to add in the footer and they don't have any dependencies. But maybe you want one of them to be at the end because it has to happen at the end. Then you can say now I want to be this resource to be the last one. But how can you do that? You can find a RequireDependencies method in the ResourceManagerTest that is about to test this new feature. Let's take a look! Here you can see that we defined a resource with the name first-resource and used the SetPosition method to set the position. The first-resource has one dependency: the first-dependency one that we have already defined in line 127. The code should inject the first-resource first but because it has a dependency to the first-dependency, the logic will inject the first-dependency resource first, then it will inject the first-resource resource. The same applies when you use the ResourcePosition.Last enum. We said that we want to define two resources as the last ones: the last-dependency and the last-resource. But the last-resource has a dependency on the last-dependency, and the last-dependency has a dependency on the another-dependency, so the correct order will be: another-dependency, last-dependency, and last-resource. Provide AdminUserId and other properties to recipes People are using recipe migrations (like the RecipeMigrator) to create content items because they can. But when you run them from setup or when you run a setup on a site, this doesn't set up some properties, like the owner of the content item. Now there is a new interface called IRecipeEnvironmentProvider that you can implement to provide different things to the recipes. The RecipeEnvironmentFeatureProvider is used to populate the environment with the AdminUserId, AdminUsername, and SiteName values that you can use when you are executing your recipes. Fix Active Directory logs an unnecessary warning during setup Let's say you activated the OrchardCore.Microsoft.Authentication.AzureAD feature during setup and configured it from the same recipe in the next step. You will see that the site is up and running but there is a warning in the log: OrchardCore.Microsoft.Authentication.Configuration.AzureADOptionsConfiguration|WARN|The AzureAD Authentication is not correctly configured. This has been fixed now by using LoadSettings() in place of GetSettings() for updating the settings in the related recipe steps. The authentication settings being entities held by the SiteSettings document, so as done in other places and for all shared documents. Demos Monaco Editor Monaco Editor is a new editor mode that is available for the Html Field. The Monaco Editor is the code editor that powers VS Code. A good page describing the code editor's features is here. Now let's see this editor in action! Let's say you set up your site using the Blog recipe. The Blog recipe contains an Article content type that will be perfect for us to play with. Head to the admin UI of Orchard Core and modify the content definition of the Article content type (Content -> Content Definition -> Content Types -> Article). Let's add a new Html Field to this content type and name it Monaco for example. Don't forget to Edit that Html Field and set the editor mode of that field to Monaco editor. You will see that there is a text area that you can use to configure the options of the editor. If you click on the Documentation for options link below you will be navigated to a page that explains which kind of options you can use in the configuration. Leave it on the default that means the editor will use the HTML language. Now if you save the content definition of the Article content type and edit the predefined Article content item, you will see the new field that you can use. You can see that it's the same editor as you can use in Visual Studio code. In this GIF we just showed you some minor functions of the editor by using the default options. But as we mentioned you can configure your editor as you want. Let's say you would like to change the theme of the editor. Modify the editor options and set the value of the theme string that is the initial theme to be used for rendering. The current out-of-the-box available themes are vs (default), vs-dark, hc-black. Let's try out the last one. There is a playground where you can find several examples to see how to use the different kinds of options. If you would like to know more about the Monaco Editor for Orchard Core, head to YouTube for a recording! Use custom settings to customize your theme In Orchard Core, you have the option to add as many settings to your site as you want. By using these settings you can set up some basic stuff like the name of the site, the default time zone, or the page title format. Some modules can provide their own settings. For example, if you enable the Facebook module, you can set the AppId, the AppSecret parameters that are necessary to make the connection between your site and a Facebook App. You can create a theme that can be easily customized just by using settings from the admin UI. To do that you need to implement your theme to support customization. But if you do that you can easily say what kind of navbar, header, logo, etc. you would like to use. Check out the following recording to see what you can achieve if you already have a theme like that. News from the community Orchard Ambassadors Toolbox Let us introduce the Orchard Ambassadors Toolbox! This repository contains a package of useful tools and content for those who want to evangelize Orchard Core. Check out the Readme.md file of the repository for a detailed description of what you can find in the repository. And if you followed us on YouTube, you may have seen our Showcasing Orchard Core CMS video that is also based on this template. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 192 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!

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

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

Culture settings deployment step, Display New menu option - This week in Orchard (21/02/2021)

New culture settings deployment step, display new menu option, sample recipes in Try Orchard Core, and many more await in our upcoming post! Orchard Core updates Disable CDN by default A lot of people were saying that there was no way to disable the CDN easily. There were issues when you are in China and you have to disable the CDN because in that case, you don't have access to the scripts that are required. And we had some required assets on the setup screen too. After some discussion, the fix is to not use CDN by default, use the locally served assets by default even in the setup screen. If you want to use CDN resources then you have to go to the settings and enable it. To do that, just navigate to the admin UI of your site and head to Configuration -> Settings -> General. And in the Resources tab, you will find the Use framework CDN (Content Delivery Network) option to enable or disable the CDN support. You can find some lines about the disabled CDN in the docs. Add deployment step for culture settings Set up your site using the Blog recipe then navigate to Configuration -> Features under the admin UI. Here enable the Deployment and the Localization features. Now you can add multiple supported cultures to your site. To do that, head to Configuration -> Settings -> Cultures and add some cultures. Now we can easily try out the new Culture settings deployment step. All you have to do is to create a new deployment plan under Configuration -> Import/Export -> Deployment Plans and add the new Culture settings to it. If you execute the plan and open the Recipe.json file inside it, you will see the supported cultures of the site. Fix NRE when clearing out all zones Let's navigate to Design -> Settings -> Zones to manage the supported zones. Remove all zones from Available zones for Layer and hit the Save button. This means the zones do not clear but instead remaining the same. The cause is an NRE in the LayerSiteSettingsDisplayDriver when attempting to split model.Zones when null. If you happen to go edit the layer zones and you make it blank, the model.Zones here will be null. You can see the fix in the LayerSiteSettingsDisplayDriver.cs. Move tags to own ViewModel Let's say you have several taxonomy terms, multiple fields with the same taxonomy terms on the editor of your content item. And if you would like to save or publish your content item you got the Form value count limit 1024 exceeded error message. The solution is to use one JSON document containing all the Tag Term entries to update and then just send what needs to be updated instead of sending everything when you are modifying your content item. Check out the Edit and UpdateAsync methods of the TaxonomyFieldTagsDisplayDriver. Demos Display New menu option If you log in to the admin UI of Orchard Core, the first option in the admin menu called New that you can use to create Creatable content items. It can happen that you don't want to be that option in the menu because you don't need that all, you never use it. Well, here comes the good news for you! If you navigate to Configuration -> Settings -> Admin, you will find a new one here called Display New menu. If you remove the tick from the checkbox, the New option will not be available from the admin menu. You can also find a short recording on YouTube about this setting! Try Orchard Core sample recipes You may hear about the Try Orchard Core website that is a showcase for the Orchard Core content management framework: you can try how Orchard Core feels by checking out an already running demo site where you can play with Orchard as you wish. This site operates with the RC2 version of Orchard Core but if you want to go ahead with a more recent dev build of the CMS, you can do that under the https://try.orchardcore.fr URL. And there is more difference between these two sites. Let's meet with the sample recipes! First, navigate to https://try.orchardcore.fr and set up a site with the Blank recipe (the third option from the recipes). If you set up your site by following the instructions from the email, you will see that the site doesn't have any home page. Now let's navigate to the admin UI of your site and head to Configuration -> Recipes. Here you will see several recipes under the Try Orchard Core category. Let's try to run them in the given order. The first one will enable the theming engine and The Default Theme for your site and make it the current one. The second recipe (called Homepage) will create a Page content type and a page content item that will be the homepage of your site. The first one (Menu) will add a new menu item to the Main Menu that targets the homepage of your site. The Layers recipe will add an Always and a Homepage layer to your site with the Content and Footer zones. The Widget recipe will create a RawHtml content type and add a Widget in the Footer zone. You will see something like this for now: the homepage has the page content type as the homepage, a menu with one item, and a RawHTML widget in the footer. Check out the following recording on YouTube to see what can you can get if you run the rest of the recipes! News from the community Work with us! You've completed the Dojo Course, congratulations! You’re now officially an Orchard Core developer. Would you like to work on a variety of challenging Orchard Core projects with the biggest Orchard team in the world? Work with us! Just send us an e-mail to crew at lombiq.com. Please include what you’re most interested in professionally and attach around 100 lines of any kind of code that you’re especially proud of or just link to the favorite open-source project of your own on GitHub or else. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 191 subscribers! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

Cypress Tests, Media Profiles background color - This week in Orchard (13/12/2020)

Have you ever wondered how to write end-to-end tests for your Orchard Core application? Check out our current post to read about Cypress, which is a next generation front end testing tool built for the modern web. But first, let's start with the other exciting improvements! Orchard Core updates Specify background color Media Profiles feature in Orchard Core is a powerful feature allowing you to specify image 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. We showed you a great demo in this This week in Orchard post about the Media Profiles feature. And here we mentioned the media crop picker and the alt text editor features with YouTube videos too. If you haven't heard about these features, you should check out those posts and videos, especially if you are dealing with several images on your website. The new feature is that now you can specify the background color for the processed image. Let's try this out! Set up your site using the Blog recipe, then navigate to the admin UI of Orchard Core. Head to Configuration -> Media -> Media Profiles and edit the predefined banner Media Profile. Set the resize mode to Pad or BoxPad. If you do that, you will see a new option here called Background Color. Using that property you can select the background color for the processed image. The hint shows you the example values, let's just put red there. Save this setting and open the predefined blog post. And in the screen below you will see our beautiful header with the red background color. If you check out the documentation of Orchard Core, you will find some examples of how you can use the bgcolor argument to set the background color of the image using Liquid Filters or by using the Orchard.AssetUrl Razor Tag Helper. Fix NRE in feature recipe step Let's say you have a recipe and in your recipe, you have a Feature step. The Feature step can be used to say which module you would like to be enabled or disabled if you are running the given recipe, like "steps": [ { "name": "feature", "disable": [], "enable": [ "OrchardCore.HomeRoute", "OrchardCore.Admin", "OrchardCore.Diagnostics", "OrchardCore.DynamicCache", "OrchardCore.Features", "OrchardCore.Navigation", "OrchardCore.Recipes", "OrchardCore.Resources", "OrchardCore.Roles", "OrchardCore.Settings", "OrchardCore.Themes", "OrchardCore.Users" ] }] Here we enabled several modules, but the disable step is empty. That's because, in this recipe, we just want to enable some modules, don't want to disable any of them. But if you define a feature step in your recipe without a disable or an enable step, you will get an NRE when executing the recipe. It's worth to mention the fix because it's very instructive. Let's see the FetaureStep IRecipeStepHandler, where you can see the ExecuteAsync method, which is responsible to process a given recipe step. The assumption is that the Contains() method returns with true or false and therefore you don't need to add the == true. And it's true. But in this case, the Disable string array can be null and if it's null, it will return null. And null equals true will be false. So, without == true the answer can be null which did not compile: "Cannot implicitly convert type bool? to bool". And now if you don't have the enable or the disable step in your recipe, the execution of the recipe won't fail. Now if you check the built-in recipes, like the blog.reicpe.json file, you will not find the disable step there because it's unnecessary. Improve sending emails from Orchard Core Email sending in Orchard Core has got several improvements lately. 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. First, now your message can have multiple authors seperated by the ',' or the ';' chars. The other is according to the following MailKit docs: "When the list of addresses in the Reply-To header is empty, replies should be sent to the mailbox(es) specified in the From header". See the related changes from line 116. Upgrade YesSql and fix multiple taxonomy filter issues The goal is to be able to filter on multiple taxonomies. The All method in the IQuery means, that all the predicates inside need to be true. And inside the All, you can call Any if you would like to. And actually, you can't have the same record with two different properties. But now you can do that multiple times and that would work, you can do an AND, it will work to have two predicates on the same index. GraphQL is building SQL queries dynamically, because in GraphQL you can have complex expressions, like ANDs, ORs, INCLUDEs, STARTSWITHs, and all the things you want on different properties. We parse that thing and convert it to a dynamic SQL. The generated SQL would have to do INNER JOINs on the index table. And it broke GraphQL. Nakamura understood how YesSql was building the query after the change by looking at the code of YesSql. And he changed the code to react to these changes by creating new kinds of dynamic SQL queries by using private reflection to get the dynamic names of the dynamic aliases. Demos Cypress Functional Tests Clone the Orchard Core repository then navigate to the tests/functional folder using Windows PowerShell and type npm install to install the packages among with the package of Cypress OrchardCore that is a collection of Cypress commands for interacting with Orchard Core. Make sure you deleted your App_Data folder inside the OrchardCore.Cms.Web folder and type npm run cms:host to build the application and run it. Check out the package.json file in the OrchardCore.Tests.Functional project to see the built-in scripts that you can use and type in the PowerShell window. Now you have a running instance of Orchard Core, time to do some testing! Open a new PowerShell instance and navigate to the same tests/functional folder. Type npm run cms:cypress, which will open the Cypress UI. After some seconds a new window will open with the Cypress test runner. Here you can run all the tests or just pick one by simply clicking on it. Since the tests generate a GUID for the site name and the URL prefix, you can rerun them over and over again. If you run a test, you can visually see what it's doing in the browser. Cypress verifies the JavaScripts too, so if there is any JavaScipt error on the page you visit using the tests, it will show you. If you hover over with your mouse in the steps on the left side of the browser, you can see what was the highlighted step actually did. Like you could see it was getting the textbox with the UserName ID and typed admin there. If you run the agency-test, you will see the following in your browser. But how can I add tests like these and where are these tests in the solution? Well, navigate to the cms-tests/cypress/integration folder of the OrchardCore.Tests.Functional folder, where you can see the exact same files as you can see in the Cypress UI. As you can see, the blog-test.js files just open the given tenant and after logging in to the site, navigates to the admin UI of Orchard Core. If the HTML element with the ta-content class contains the Welcome text, it means that the login was successful. And that's not all of it! If you would like to know more about Cypress testing, check out this recording 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 :). 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 174 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!

Secret Management Updates, ChallengeOrForbid() in Api controllers - This week in Orchard (18/09/2020)

This week you could see two great demos: one is about showing you how you can manage and import/export your secrets between servers, the other is about using Blazor WebAssembly with Orchard Core! Orchard Core updates ChallengeOrForbid() in Api controllers Most of the API controllers are configured to use the Api scheme for authentication but return ChallengeOrForbid(), which ultimately uses the default challenge scheme (which is typically the cookie handler when the Users module is enabled). To fix that, the API controllers are updated to do ChallengeOrForbid("Api") instead of ChallengeOrForbid(), so that challenges are properly handled by OpenIddict when the OpenID token validation feature is enabled. Now there is a new override for the ChallengeOrForbid() extension method that accepts the authentication schemes to challenge. And now you can use this extension method in your API controller just by passing the Api, like: return this.ChallengeOrForbid("Api");. Include ContentsMetadata (PageTitle) in Blog Theme Category Taxonomy If you use the Blog recipe, a taxonomy Category with entry Travel is created by default. However, the title for the Travel page was not correct. If you created a site name Blogging using the Blog recipe, the expected title would be: Travel - Blogging, but you got a title: Blogging. The fix was to include the ContentsMetadata in the Content-Category.liquid file. Link to GitHub Discussions in Contributing If you open the GitHub repository of Orchard Core you will find a CONTRIBUTING.md file in the root of the repository. Now this markdown file has a direct link to GitHub Discussions. But what is GitHub Discussions? GitHub only offered issues and pull requests as places to have these conversations. But issues and pull requests both have a linear format - well suited for merging code, but not for creating a community knowledge base. Conversations need their own place - that’s what GitHub Discussions is for. If you have a question and need an answer, just visit the Discussions page and if you haven't find the answer for your issue, let's ask it there. Here you can find detailed and valuable answers for questions like what is a shape? Demos Secret Management Updates Head to the GitHub repository of Orchard Core and checkout to the deanmarcussen/secrets branch to be able to try out this upcoming feature! After you set up your Orchard Core site, head to Configuration -> Features and enable these features: Configuration Secrets Store: The secrets configuration store is a read-only store for secrets. Database Secrets Store: The secrets database stores encrypted secrets in the database. Secrets: The secrets feature manages secrets that other modules can contribute to. After you will find a new option under Configuration called Secrets. Here you can add two kinds of secrets: Authorization Secret: A secret used to manage a secure password or authorization key. Rsa Secret: A public / private RSA key pair used for encryption. Let's add a new Authorization Secret now and see what are Secret Bindings exactly? Secret Bindings can be used to enter secrets, like SMTP passwords. And you can choose where it's gonna come from. Right now they can be stored either in the database or in the configuration. But there is a plan to support the Key Vault provider as well. Let's use the smtp_password as the name and store it now in the Database Secret Store. And add the password into the Authentication String textbox. But how can use that secret? If you enable the Email feature, you can navigate to Configuration -> Settings -> Smtp and set up the network delivery options. If you put a tick on the Require credentials checkbox, you have to provide a user name and a password for authentication. If you would like to use your secret, you can use a Liquid filter to access the password stored in it. Here you can see that we entered the following Liquid expression to retrieve the password: {{ "smtp_password" | auth_secret }}. Remember, the smtp_password was the name of our secret. When we added our secret, we had the option to choose to create an Authorization Secret or an Rsa Secret. We created an Authorization Secret, so let's create an Rsa Secret this time! The RSA key pair is what we could use to actually crypt secrets when transmitting them to another server. At the moment the private key is in the editor, the idea is that once you created the private key you will never see it again. You can use the public key as an encryption key. Now let's create a new Deployment Plan and call it Secrets RSA! Add the All Secrets deployment step to it then hit Execute! After you will end up with a recipe that looks like the following. Here you can see the encriptionKey used for this particular recipe. It's a symmetric encryption key that is encrypted with the public key from the RSA key pair. Then all of the bindings that are available are here in the recipe. You will also find a decryptor here (js: decrypt()) which will use the encriptionKey and the private key on the other end to decrypt them. And when you run this recipe on your remote server - assuming you have installed the private key on the remote server - it will unencrypt your secrets correctly. But it's not all! If you would like to know more about this great upcoming feature, don't hesitate to watch the recording of it! Blazor WebAssembly with Orchard Core In this demo, you will see how to use a Blazor WebAssembly application that queries a blog post content through a REST API call using GraphQL. A JWT token used as a bearer token when calling the REST API GraphQL endpoint. Head to YouTube now to see the full demo! News from the community Orchard Dojo Newsletter Now we have 159 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 Impersonation, Export Content To Deployment Target - This week in Orchard (07/08/2020)

This week we are gonna show you three brand new features that are recently added to Orchard Core: the Add Content To Deployment Plan, the Export Content To Deployment Target, and View Or Download Content As JSON features. After we see a demo about user impersonation and finally we solve the mystery about what is GitHub Arctic Code Vault? Orchard Core updates Add Content To Deployment Plan, Export Content To Deployment Target, and View Or Download Content As JSON features Set up your site using the Blog recipe. Now you can head to Configuration -> Features and enable the Add Content To Deployment Plan, Export Content To Deployment Target, and View Or Download Content As JSON features. This will bring you several new stuff that you can use when you are managing the content items. If you click on the Actions button you can see that the context menu is now getting a lot more items. The Export to Deployment Target is about to automatically create a custom recipe file that can be downloaded locally or send it to a remote instance. You can use the Available Targets modal to select the destination. The Add to Deployment Plan is about to add a new content item step using this content item to an existing deployment plan. In this case, a new modal window will open again that lets you choose from the available deployment plans. The Download as JSON is about to directly download the recipe to your computer locally and the View as JSON is a very helpful feature because as you could see in the screen below it shows you the JSON representation of the content item. The same JSON will go to the content step of the recipe when you are hitting the Download as JSON button. Here you have the availability to copy the JSON structure by clicking on the copy icon at the top-right corner of the page. And don't forget that you can find two demos on YouTube about this feature. Click here for the Click to deploy demo and here to see the second part of the demo! Add authentication checks to some ISite drivers We had some drivers in Orchard Core where we hadn't check that the user has the appropriate permissions to modify the changes of given settings because the controllers won't do that for us. For example, if the user would like to change the settings of the reCAPTCHA, then we have to make sure that the user has the ManageReCaptchaSettings permission to do that. Now, these missings checks are added to the code. Fixing Linux setup by making sure a directory created before creating a file Let's say you would like to host your Orchard Core site in a Linux environment. But unfortunately, the setup failed on installation from Docker-Linux container. The strange issue was a directory needed to be created before file creation. Navigate to the SaveContentDefinitionAsync method of the FileContentDefinitionStore to see the check for the directory. Document HTML Sanitizer and Markdown Pipeline Options An HTML Sanitizer is available as part of the Orchard Core Infrastructure. The Sanitizer cleans user input that could lead to XSS attacks. From now you will find a new page in the Orchard Core Documentation about how to use the Sanitizer in your Razor view, how to configure the Sanitizer in the Startup classes, and much more. Markdown output is also sanitized during the rendering of content with Display Management. This page contains new sections about how to enable/disable or configure the Markdown Sanitization using the MarkdownPipelineOptions. Demos User impersonation Open GitHub in your browser and navigate to the OrchardCoreContrib.Modules repository. This repository contains a set of modules for Orchard Core CMS driven by the community members who love Orchard Core. Here we will focus on the one called Impersonation. That feature allows administrators to sign in with other user identities. To try this out, let's clone or download this repository then set up your site using a chosen recipe. After, navigate to Configuration -> Features and enable the Impersonation feature. To try out the impersonation, we need to have multiple users in the system. Go to Security -> Users and click on the Add User button to add a new one. In this case, we created a new user with the Author role with the author user name. In the users list, you will find a new green button called Impersonate. Here the Impersonate button is disabled for the admin user because we have already signed in with that user. So, click on that button near the user named author and see what will happen! You could notice a slightly changed admin UI in this case. The reason for that is quite simple: users with the Author role have access to the admin UI with some content and media library-related permissions. So in that case you can do and you can see what this exact user can see and can do in that site. It's a good way to for example test the permissions and the rights for that user. If you would like to end the impersonation and return your work using your account, you can just simply have to navigate to Security -> End Impersonation, that will do the trick for you. If you are interested in the full demo, head to YouTube for the recording! News from the community Orchard Core on GitHub Arctic Code Vault The GitHub Arctic Code Vault is a data repository preserved in the Arctic World Archive (AWA), a very-long-term archival facility 250 meters deep in the permafrost of an Arctic mountain. The archive is located in a decommissioned coal mine in the Svalbard archipelago, closer to the North Pole than the Arctic Circle. GitHub captured a snapshot of every active public repository on 02/02/2020 and preserved that data in the Arctic Code Vault. And why it is important? Because Orchard Core also sits in this Code Vault! If you have contributed a repository that is in the Code Vault you will see that in your GitHub profile! Check out this exciting video about the GitHub Arctic Code Vault! Lombiq Offline event Sometimes it's not just about work but doing something just for fun. These events are specifically for this: we get together, do something cool like breaking out of an escape room, going for a go-kart ride, or playing paintball. A few days ago we went hiking then we went back to Budapest in a boat. Check out this new picture of our team, shot at our Lombiq Offline event! While here in Hungary there are no restrictions on events like this anymore, we played it safe with a fully outdoor program. You can find this new picture on our About us page too! 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 156 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!

Export contents as setup recipe, Shape Debug Mode to dynamic cache - This week in Orchard (24/07/2020)

Export contents as setup recipe and import recipe from JSON are about to make it easier to manipulate data and setup your Orchard Core site. Edit cached shapes using the Shape Debug mode to see your changes right away. We think if you are an Orchard Core developer, you will find these features very useful. These are the bigger topics for this week! Orchard Core updates Export Contents As Setup recipe This is a new feature that allows you to use a checkbox when you want to export some content and remove any information that would reuse properties like the content item ID, author, owner. Let's see an example for this and create a deployment plant that contains only that All content deployment step and see the JSON schema of the Blog content item that you can get if you install your site using the Blog recipe. So, if you leave this checkbox unchecked, you will see the following content. Nothing special here, you see the same content as you saw before. The content item has an ID, a version ID, and the dates when this content item was published and modified. But let's see what will happen if we put a tick in that checkbox! In this case, all the IDs are regenerated (for now it's not the case for the contained content items) and the values for the owner and the author are coming from the AdminUsername parameter. But be aware of the note that you can read under the checkbox: If checked, you will have to manually declare variables for the Content Picker fields, Taxonomy fields, Tags fields, and List item ids and replace them where needed in the recipe. Any reference to these content items will be lost. And the logic in the ContentDeploymentSource is about checking the value of the ExportAsSetupRecipe boolean property. If you want to export contents as a setup recipe, then the related properties of the objectData will be changed as you can see in the recipe file. We have to mention one new thing here. If you add the All features deployment step to your plan that exports the state of all features, you can say to ignore the disabled features. In that case, your recipe will only contain the enabled features and not the disabled ones. Import Recipe from JSON If you navigate to Configuration -> Import/Export in the admin UI, you will see a new option called JSON Import. This new feature will let you type some JSON and then run it, so you can execute some custom recipe steps from this UI. This new edition comes with the Deployment feature and it's using permission which is the Import permission. Let's say you want to change the site theme of your site for the default one. To do that you can use the following JSON. You can see you can do it in the same way as you would do it in a recipe file. Fix modules referencing other modules You may notice how many modules are referencing other modules for no need. Mostly this is just because they are doing so to get transitive references. The solution was to take direct references on the required abstractions/core projects instead of transitively depending on other modules to provide those references. Dean Marcussen also reviewed other references, removed superfluous references, and ordered them all. Migrate the OpenID module to OpenIddict 3.0 OpenIddict 3.0 has matured enough to envision using it in Orchard Core 1.0 RTM for both the server and validation features. As part of this migration, a few properties will be added to OpenIdServerSettings and OpenIdValidationSettings and others will be renamed for clarity. Due to this change, existing deployments will have to be updated to use the revamped settings. No exception should be thrown and the migration should be limited to re-configuring the server/validation options using the UI and/or updating custom recipes to use the new names. An important aspect of this migration is that the validation feature will now internally use the OpenIddict validation handler instead of the Microsoft JWT bearer handler, even with external OAuth 2.0 authorization servers. Unlike the MSFT JWT handler, the OpenIddict validation handler uses the new Microsoft.IdentityModel.JsonWebTokens stack and comes with JWT token type validation enforced by default, which is required by the not-yet-standardized JWT access token specification. This change will break existing deployments targeting OAuth 2.0 authorization servers that don't issue "typ": "at+jwt" access tokens. At least the following implementations are known to be impacted: Azure AD/B2C. IdentityServer3.IdentityServer4, except its latest 4.0 version (unless 4.0 is configured to use a different typ header) OpenIddict-based deployments are not impacted, as the validation handler includes special logic to deal with the tokens produced by OpenIddict 1.0 and 2.0, whose JWT tokens always include a special token_usage claim to prevent token substitution attacks, which has the same purpose as the "typ": "at+jwt" header. To ensure the validation feature can still be used with servers that don't issue "typ": "at+jwt" access tokens, an opt-in option was added to the validation configuration UI. This option can only be enabled when configuring a remote OAuth 2.0 server and is not shown when using a local OpenID server or a server located in another tenant, as OpenIddict 3.0 always issue "typ": "at+jwt" access tokens. Demos Shape Debug Mode to Dynamic Cache If you have a lot of menu shapes in your site and if you want to edit the templates you can't do that easily because the items are cached. The solution here is to provide an easy way to disable the cache, so in that case, the menus will not be cached. To set the cache mode, head to Configuration -> Settings -> General, where you will find a new tab called Cache. The settings here are very similar to the resource settings, the default is that the cache would be enabled in production and disabled otherwise. You can say I want to enable or disable it all the time. And there is a very useful option called Enabled with cache debug mode. Let's select this one and see what will happen! Now navigate to the homepage of your site and view the page source. Everywhere where is a cached block you will get a little piece of information about the given block. It shows you the cache ID, the dependencies that it's using, how long it's cached for, and any of the variations that are present. You will also see where is the end of the block. Let's see how it works! You will find a CacheStatement class that is about to check the value of the cacheOptions.DebugMode and if it's true, then it will add the additional content to the source of the page. If you are interested in more details about the cache settings, head to YouTube, and see the recording of the demo! News from the community 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 154 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!

Publish Later feature, Tags - This week in Orchard (13/03/2020)

The Tags feature is now merged to the dev branch of Orchard Core! In our post, you can also read about the improvements of the Content Picker field, see a demo about the Publish Later module and many more! Orchard Core updates Make content picker default to displaying all content types when none are selected There is no reasonable use-case for a content picker to be configured with no DisplayedContentTypes other than it just hasn't been configured yet. On the other hand, it seems reasonable that some circumstances may necessitate picking a content item of an undeterminable content type at setup. So, by using the content picker you could select which content types you wanted to display in the list when you are searching for a content item. Now there is a new option which is called DisplayAllContentTypes. This way when you add a new content type you won't have to select it again when specifying the content types to display in your content picker. To try this out just simply add a new Content Picker Field to your type and then head to the settings page of the field. Here you can find the Display All Content Types checkbox, that we have just mentioned before. Put a tick in this box and then create a new content item of your content type. We have added a Content Picker Field to a Page content type. Here you could see that the list of the picker is showing menus, landing pages (named Orchard Core) and page content items, so, everything is here that we have defined on our tenant. Tags The tags PR was merged to the dev branch of Orchard Core. The editor of it shows the list of taxonomy terms as tags and stores every DisplayText of every taxonomy term that is tagged inside the field itself under a custom dynamic property which is not available on the field class itself, but there are extension methods called GetTagNames and SetTagNames to retrieve and set the name of the tags. There is a property on the field itself (on the JSON document of the field) that's called TagNames, that gets all the tag names as a string array based on the DisplayText, when a tag was added to the content item. If you change the DisplayText of a term, then every existing content item that was tagged with this term won't have the new DisplayText. That's a caveat for using this property, the GetTagNames on the field. But it would be super useful when you want to just list the names of tags and the TagNames never change, which they should never do. Don't change the name of the tag from one day to the other. If you do, then your responsibility to update the content items or not to use the TagNames property, but resolve all the content items for every tag and use a dynamic DisplayText. Maybe we want the same possibility on even the default TaxonomyField. And have that property on the field itself as a static property, by explaining the limitation of this property. You can see great demos on YouTube about tags using taxonomies and Open Tags. We have already mentioned these demos in the following This week in Orchard posts: Tags using taxonomies Open Tags Fix for SameSite cookie issue By following the recommendation of the ASP.NET team, now we are checking that based on the browser vendor ID what default value we should send for the SameSite cookie. Most of the servers never set the SameSite property of the cookie. It used to be a default value like None by default. But now Google assumes that no value will mean Lax. So, if you want to keep the None value (that was before by default) we have to set it. There is an update on the ASP.NET framework that set's it by default but there is configuration to change the behavior. But this behavior should not change for some browsers that won't be updated. And this is why the only solution is to check what kind of browser is doing the request to know what value we need to set as the default, like Unspecified, None or Lax or whatever. That's an issue and this is done now. Maintain content item ID across BagPart.ContentItems Before this code every time you would change the elements of a BagPart (even updating some properties), it would regenerate some content item JSON payload for each of the BagPart items, which means the content item IDs would be unique, but new. And it would cause issues when you do workflows or when you do routing for containers. Now the content item IDs are immutable even for BagParts. Recipe properties step There is a new deployment step called Recipe File that lets you define customized properties of the recipe file. If you want to customize the recipe file you have this step and then you will be able to set the properties that you can see on the screen. Demos Publish Later module In the admin UI, head to the Configuration -> Features and enable the Publish Later feature. This module adds the ability to schedule content items to be published at a given future date and time. If you would like to use this feature with your content type you have to edit its definition by attaching the Publish Later Part to it. Let's attach the Publish Later Part to the Blog Post content type! Now create a new blog post! At the bottom of the editor, you will see a new input Tag Helper with the datetime-local input type. If you set the date and the time here and hit the Publish Later button, the current version will be saved as a draft and at the given time it will be automatically published by using a background task. We also have a Cancel Publish Later button, so we can cancel the publishing process from here. And in the SummaryAdmin list, you also had a little message that shows you the date and time when the content item will be published. If you are interested in the full demo, don't forget to watch the YouTube video about it! This contribution is sponsored by a company called Weiss Ratings. News from the community How we are dealing with the coronavirus pandemic? In light of WHO characterizing the Coronavirus outbreak as a pandemic we wanted to disclose how we're dealing with the issue: https://lombiq.com/blog/how-we-are-dealing-with-the-coronavirus-pandemic Orchard Dojo Newsletter Now we have 124 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!