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 >

Fluid Functions, Lombiq Training Demo updates - This week in Orchard (04/02/2022)

Fluid provides optional support for functions, optimizing SlugServie and MediaTokenService, and hiding a shape sample in the Lombiq Training Demo for Orchard Core are the topics of this week. Check out this post for the details! Orchard Core updates Optimize SlugService The goal here was to increase the performance of the SlugService as much as we can. Marko Lahma went through the thing, and the problem was that the ZString haven't been used, it was leaking all the time thus bad perf. BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores.NET SDK=6.0.101 [Host] : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT DefaultJob : .NET 6.0.1 (6.0.121.56705), X64 RyuJIT General easy rule (when implicit usings aren't being used): If there's using System.Linq; at the top of the performance-critical code, try to find a way to get rid of it. Reduce allocations in MediaTokenService and improve performance Since Orchard Core can use all .NET 6 goodness, Marko Lahma improved the performance of the MediaTokenService too. And what did he change? Don't ToString StringValues, keep them as-is as in dictionary once built. Parse commands and other commands with one pass using constructs that QueryHelpers uses. Allocate static command arrays to return from processors, some of them were always returning new ones. Change GetHash not to allocation anonymous closure each time by using Try/Set construct, using the same logic that extension method GetOrCreate uses. Change hash calculation to use stackalloc and spans for workloads < 1024 bytes (common case). Use the custom AddQueryString method that understands spans and concrete a dictionary type. Here you can see the numbers: Before: After: Fluid functions Now there is a new optional feature in Fluid called Functions. It's optional because the goal of Fluid is to be able to as close as possible to Liquid, but Liquid doesn't have Functions. If you open up the readme file of Fluid, you can see a new section there called Functions. There is a new option in the FluidParser that you can say AllowFunctions. By setting the AllowFunctions to true, you can call functions like this: {{ field('user') }}. The format of this one is {{ identifier('arguments')}} just like in JavaScript or in C#. Or you can say {{ field('pass', type='password') }} which is like {{ identifier('values', type='named value') }}. How it works is a field is an object, a FluidValue of type FunctionValue. In Fluid, anytime we access something like {% assign name = "Bill" %}, the name is a FluidValue, and in this case, the type is StringValue. When we find a field, the field is a value of type FunctionValue, and the FunctionValue implements the method name InvokeAsync. There is InvokeAsync, there is GetPropertyAsync, etc., everything that an object can do, and when this FunctionValue's Invoke is invoked it will execute something. And to invoke a FluidValue you use parenthesis. If we do parenthesis on something like name, which is a string, we can do name(), it will invoke the string, but it just returns NIL value. So you can invoke name if you want, it will not do anything. If it's a function, it will do something. To learn more about Functions, check out the documentation of Fluid! News from the community Hiding a shape sample in the Lombiq Training Demo for Orchard Core The Lombiq Training Demo for Orchard Core is a demo Orchard Core CMS module for training purposes guiding you to become an Orchard developer. And the module has a new sample, which is a shape table provider that hides shapes. Check out the code of the new ShapeHidigingShapeTableProvider here! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 240 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!

Fluid updates, Better NRE handling for Widget and MenuItem stereotypes - This week in Orchard (07/01/2022)

Topics for this week are the Fluid updates; better NRE handling for Widget and MenuItem stereotypes; allowing sending emails without "To" if "Cc" or "Bcc" is provided. Do you want to know more? Then check out our post now! Orchard Core updates Allow sending emails without "To" if "CC" or "BCC" is provided Let's say you have a system to send emails to many recipients at once and want the recipients to be in the BCC header instead of the To one. The email module of Orchard Core was required to have at least one recipient in the To header, so, the scenario described above cannot be implemented in Orchard Core. The solution for this is that now you can send an email without a recipient in the To header. The mail message should have at least one of these headers: To, CC or BCC. Here you can see the editor of the Send Email task where we provided an email address for the BCC header but kept the To and the CC headers empty. Fluid v2.2.8 In Liquid, you can have an identifier that starts with a number like: {% assign 1st = "first" %} {{ 1st }} It was not easy to parse, but now Fluid supports this one with version 2.2.8. And just a note here. If you navigate to the Liquid Sandbox of Jumpseller, you can find a sandbox that is using Liquid but in Ruby, which is the actual implementation of Liquid. You can use LiquidJs to test, but that is a custom implementation in JavaScript, so it might not be as true as the Ruby implementation. Better NRE handling for Widget and MenuItem stereotypes As you may guess, the NRE handling is about catching the null reference exceptions and showing proper error messages instead of displaying the "An error occurred while executing this request.". What were those errors? For example, follow these steps: Create a new content type with stereotype = MenuItem. Add a menu item of that type to a menu. Delete the content type created in step 1. Go back to the menu you created in step 2. Observe a Null Reference Exception. Here we created a new content type with the MenuItem stereotype called NewContentType. The site that we are using was set up by using the Blog recipe, so we have the Main Menu admin menu where we can easily add menu items by just clicking on the Add Menu Item button. And if we delete the NewContentType and navigate back to the Main Menu, we will see the following messages instead. News from the community Lombiq's Open-Source Orchard Core Extensions now updated to Orchard Core v1.1 Looking for some useful Orchard Core extensions? Here's a bundle solution of all of Lombiq's open-source Orchard Core extensions (modules and themes). Clone and try them out! This is an Orchard Core CMS Visual Studio solution that contains most of Lombiq's open-source Orchard modules and themes, as well as related utilities and libraries. Please keep in mind that only those extensions are included which use the latest released version of Orchard (i.e. the very cutting-edge ones depending on a nightly build are not yet here). And this project, with all of our Orchard-related projects, is now updated to Orchard Core v1.1! Check it out here! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 235 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!

Statically typed URL creation, fix CSS intermittent encoding issue - This week in Orchard (22/12/2021)

Updating the Correlate Task, fixing CSS intermittent encoding issue and a demo about statically typed URL creation! Do you want to know more? Then check out our last post of this year! Orchard Core updates Fix Correlate Task If you have Workflows enabled in your solution, you have the option to add a Correlate Task to it. The hint is saying that it supports Liquid, but the truth is the parser here supports JavaScript, not Liquid. So, the solution here is to update the wording of the hint. And from now, if you would like to provide the value for your Correlate Task, you can use a Monaco editor here. Fix CSS intermittent encoding issue The cache on the browser was serving the CSS files using differently than UTF-8. When you disabled the cache on the browser it was fine. So, the cache is storing it as ASCII and not UTF-8. If you check out the picture below, you can see some weird characters on the screen. So, the problem here was a charset issue because browsers can handle different charsets if you put the information at the top of the file. But some of the stylesheets of Orchard Core were started with some comments and not with the line which is saying the given charset. And it looks like browsers only include the charset if it's in the first line of the stylesheet. So, the headers for the stylesheets are not injected anymore. Demos Statically typed URL creation The Lombiq Helpful Libraries for Orchard Core contains various libraries that can be handy when developing for Orchard Core CMS, to be used from your own Orchard modules. The Helpful Libraries now has a new class called TypedRoute which provides a strongly typed way to generate local URLs for Orchard Core MVC actions. It uses lambda expressions to select the action and provide arguments. Use TypedRoute.CreateFromExpression<TClass>(...).ToString() or the provided OrchardHelper.Action() and HttpContext.Action() extensions. Let's see this in action! In this demo, we will go with the quicker way and use our Open-Source Orchard Core Extensions full Orchard Core solution that contains that module with a nice sample. If you clone that repository and set up your site using any setup recipe, let's just navigate to the admin UI of Orchard Core, and under Configuration -> Features, enable the Lombiq Helpful Libraries for Orchard Core - Samples feature. Now, head to the /Lombiq.HelpfulLibraries.Samples/TypedRoute/Index URL to see the content of the following Razor file. As you can see, we constructed the first URL by using the anchor tag helper from ASP.NET Core. Here we needed to pass the area, the name of the controller, and the action and put the names of the accepted properties by the controller action by using the asp-route- prefix. If you use the extension, you can statically enter the controller name (TypedRouteController in this case) and using lambda you can select the TypedRouteSample action by passing the values you want. In this way, you can safely rename the controller or the action without breaking any functionality in your Razor file, because Visual Studio and Rider will also be able to find the references in your Razor files too. Do you want to know more and look under the hood of this feature? Well, you just need to check out this short presentation on YouTube! News from the community Christmas in Lombiq Sometimes we do stuff. Together. Not (just) in front of computer screens. These are some usual events in Lombiq that are all announced and arranged in advance. We periodically have an event called RnDay: this is a few hours long event where we share with each other what we recently worked on and what we plan to do. E.g. if we recently finished a project then the project's team members demo what they've done. This week we had our last RnDay for this year but this time (again), we have to make it online. We also named this event The 14th RnDay - Pandemic Edition 2! We also tried to do our best to make a nice group photo, you can see the result down below. :) We would like to thank you all for reading our posts and making the Orchard community stronger together with us! We hope that we could give you valuable news and demos about the happenings around Orchard and Orchard Core from time to time by reading our posts and of course the This week in Orchard newsletter. We would like to wish everyone a Merry Christmas and a Happy New Year! See you next year! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 234 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!

Fix Liquid QueryCollection access, renaming page route parameter - This week in Orchard (04/12/2021)

Fixed Liquid QueryCollection access, an interesting bug when using the page route in Razor Pages, and updated libraries used in Orchard Core. Check out our current post to read about the details! Orchard Core updates Pager used the reserved "page" route parameter The bug only happens if you are using Razor Pages at least one razor @page. In that case when you list the items of a given content type e.g. /Admin/Contents/ContentItems/Article?admin=674211458, the Pager links, in place of using our custom pattern /Admin/Contents/ContentItems/Article?admin=674211458&page=2, they use the default pattern where the content type is a query string parameter /Admin/OC.Contents/Admin/List?contentTypeId=Article&admin=...&page=2. At this point, you can still go to a given Pager page. But then if you select a new filter option it removes the above query string contentTypeId parameter e.g. /Admin/Contents/ContentItems?q=status%3APublished. So in place of still listing the items of a specific content type, you go to the list of all content types in place of staying in the list of a specific type. Removing the contentTypeId parameter is another issue filtering should preserve the existing parameters, but here we're only talking about the fact that the Pager links don't use the right custom pattern if at least a Razor @page is defined. This is because the Pager uses a page route parameter to generate link URLs, but this is a reserved ASP .NET Core routing name. The solution is to remove this route value in the ActionLink shape before generating an URL and then explicitly add it as a query string parameter. Currently, as a workaround, there is a custom IShapeTableProvider. So in one sentence, you are not allowed to use page in routes because it's a reserved word because of Razor Pages. And now it has been changed to pagenum everywhere. Fixed Liquid QueryCollection access Let's set up your site using the Agency recipe. That recipe contains a template for the Landing Page content type where we can test the Request.Query Liquid filter easily. If you check out line 19 of this template, you can see that we are using the Request.Query Liquid filter to say, give me the value of the test field from the query string. But how can you use this one? The helper is just about to print the value of the query string by the given field. So, if we open up the predefined Landing Page content item and put something in the query string using the test, you will see the printed value on the page. It's an IQueryCollection whose underlying type is a QueryCollectionInternal, but we only allow access to QueryCollection. Jean-Thierry Kéchichian fixed it by creating a QueryCollection. Updated libraries We have this Libraries page in the Orchard Core documentation that lists the different .NET libraries, the different Client-side libraries, and the different Tests libraries used in Orchard Core. In Orchard Core, the community always tries to use the latest versions of these libraries to make sure you will always get the latest bug fixes and the latest features provided by these libraries. News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 233 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!

Feature profiles deployment plans and recipes, Support ordering in list_items Liquid filter - This week in Orchard (13/11/2021)

Feature profiles deployment plans and recipes, Audit Trail updates, support ordering in list_items Liquid filter, and many more coming this week! Do you want to know more? Then don't forget to check out our current post! Orchard Core updates Feature profiles deployment steps and recipes The Feature Profiles is about adding the ability to restrict the features and/or themes that are available to either a tenant and/or all tenants or a mix of both. If you haven't heard about that feature yet, check out this post with a great demo! This time you will see that now you can export and import your existing Feature Profiles. Let's assume that we have already created two Tenant Feature Profiles. To do that, you have to enable the Tenants and the Tenant Feature Profiles feature under Configuration -> Features and add Feature Profiles under Configuration -> Tenant Feature Profiles. Now you can go to Configuration -> Import/Export and add a new deployment plan. If you click on the Add Step button and search for the feature keyword, you will find a new one, called All Feature Profiles. Choose this one and execute the plan by downloading the given zip file to the computer. If you check out the Recipe.json file inside the zip, you will see a step called FeatureProfiles which contains the available feature profiles that we have already created: restricted profile and restricted agency theme. Fix Audit Trail date parsing The Audit Trail module has a huge update this summer where the UI had been totally changed, and the feature had some new stuff too, like the improved search filters. In this post, we had a detailed description of everything you may need to know about the improvements of the Audit Trail module. When you open up the Audit Trail module, you can find a funnel icon. 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. When working with dates, you have several options, like date:>2021-11-08, which means give me all of the events that happened after the 8th of November this year. Or you can say date:>=2021-11-08 to get all of the events that happened after the 7th of November this year. There was a minor bug in the DateTimeParser when it splits the operators. The OneOf() method builds a parser that returns either of the first success of the specified parsers. And the first one was the > operator, which means if you wrote >= for example, the parser used the > operator because it was defined earlier than the >=. The same goes for < and <=. Fix ambiguity in search form settings If you go to Search -> Settings -> Search on the admin UI of Orchard Core, you will see that the Default search index drop-down has a value to use for the search page. But this doesn't mean that the given index is the default one. Here you see a value, but it's not set it's just the first item in the drop-down. Now there is a new Select a search index option in the drop-down that will alert the user about there is no default index to use for the search page. Demos Support ordering in list_items Liquid filter We have a list_items Liquid filter which loads published content items for a given content item object or explicit Content Item id given as a string in a list. You can see a nice demo about how to make lists sortable with ordering setting here. This time this demo is just about showing you that now if you use the list_items Liquid filter with a ListPart where the ordering is enabled, the filter returns the list items in the expected order. The code changes are in the ListItemsFilter class (which is the implementation of the list_items Liquid filter), where you can see that we get the ListPartSettings by using the IContentDefinitionManager. If the ordering is enabled for that ListPart we pass the bool value to the QueryListItemsAsync method. That method is just containing a query that returns the content items of the given list. The change here is to order the content items by the ListContentItemId if the partPredicate value is true, which will be true if the ordering of the given ListPart is set to true. You can find the code in the following PR and as always, if you would like to know more, head to YouTube for a recording! News from the community A new website using Orchard Core: eRED Real estate and development The eRED Real estate and development site has been developed by one of the contributors of Orchard Core, Sotiris Roussos. Check out this brand new Orchard Core site here! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 232 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!

URI components Liquid accessors, Lombiq JSON Editor - This week in Orchard (15/09/2021)

Add Cc and Bcc to Workflow Email Task, URI components Liquid accessors, Lombiq JSON editor, and many more coming this week! Do you want to know more? Then it's time to check out our current post! Orchard Core updates Add Cc and Bcc to Workflow Email Task If you would like to send an email using Workflows, you can use the Email Task to achieve your goal. Simply navigate to the admin UI of Orchard Core and go to Workflows (don't forget to enable the Workflows and the Email features) to create a new workflow. If you add a new Email Task to your workflow, you will see that this task has now two new fields: the Cc and the Bcc. RegisterUserTask: Subject & Template for confirmation email should not be required if Send Email is unchecked And while we are talking about the workflows, let's check out another workflow task, the Register User Task which registers users from form fields. When adding this task to your workflow, you can easily say that I want to send a confirmation email to the newly registered user with this subject and template. The issue was that the subject and the template for the confirmation email were required even if Send Confirmation Email is not checked. URI components Liquid accessors By default, the Liquid templates have access to a common set of objects. You can easily access the properties of the content item that is currently being rendered, the authenticated user for the current request, the current site settings, and the current request itself of course. Check out this page of the Orchard Core documentation to see all of the available properties on the Request object. If you use the Request object quite often, you will notice that this table now has new properties, like the QueryString, UriQueryString, Path, UriPath, PathBase, UriPathBase, Host, and UriHost. Generate Rule Condition TargetUrl in a correct location The rules module was designed with extensibility in mind; however, there is one line that is in the view for it, setting the TargetUrl property of the modal picker to the layers controller. It needs to be moved out of the view, and into the Layers controller so that the view can be used by other modules, pointing to different controllers. Demos Lombiq JSON Editor The Lombiq JSON Editor is our Orchard Core module for displaying a JSON Editor like on jsoneditoronline.org. You can easily clone or download the module from this GitHub repository. If you want to quickly try out this project and see it in action, check it out in our Open-Source Orchard Core Extensions full Orchard Core solution and also see our other useful Orchard Core-related open-source projects! In this demo, we will go with the quicker way and use our Open-Source Orchard Core Extensions full Orchard Core solution. If you clone that repository and set up your site using any setup recipe, let's just navigate to the admin UI of Orchard Core, and under Configuration -> Recipes, you will find one called Lombiq Open Source Orchard Core Extensions - JSON Editor Sample that is about demoing the Lombiq JSON Editor module. Let's run the recipe! Now let's see the list of the content items where you will find a new one called JSON Example Page. This page has a JSON Field which comes from the Lombiq JSON Editor module. It's using a tree editor by default that you can use to manipulate the content of the JSON inside. But of course, you can have other types of editor for your JSON if you want, like you can have a code editor with numbered lines with syntax highlighting or you can just use a pure text editor and so on. Using a simple json-editor tag helper you can easily render the JSON editor. You can pass a string value to the editor that will contain the JSON itself, pass the JsonEditorOptions class that contains several configuration values like EscapeUnicode, SortObjectKeys, and so on. And you have several other options and use-cases for this JSON field. The JSON Example Page, which comes from the recipe, has a Liquid Part too that reads the values from the JSON field and prints the values in a simple list by using Liquid and JavaScript. Here is the display view of the JSON Example Page. If you would like to know more about this new field, head to YouTube for a recording! News from the community New GraphQL sample in the Lombiq Training Demo for Orchard Core The Lombiq Training Demo for Orchard Core is a demo Orchard Core CMS 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 includes the full source code - which is the recommended way. You can also use it as part of a solution that uses Orchard Core NuGet packages; however, it's harder to look under the hood of Orchard Core features. And the module just got a new little GraphQL sample! Check it out if you would like to know more about Orchard Core's GraphQL module and learn how to extend the Orchard GraphQL APIs! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 226 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!

Add UsersFolder for media assets, Liquid IntelliSense for Monaco editor - This week in Orchard (18/08/2021)

Updating Monaco editor to have Liquid IntelliSense, new UsersFolder for media assets, a brand new Orchard Core website, and many more in our upcoming post! Orchard Core updates Add UsersFolder for media assets Open up the admin UI of Orchard Core and head to Content -> Media Library. Here you will find a folder called _Users. Under this folder, you can find three different ones where each folder has the name by an ID of a given user. The reason for that is, we have three users in the system right now who have access to manage the content of the media folder and the content of their own media folder. If you check the permissions page for one of the roles you will see some new permissions come from the OrchardCore.Media feature: Manage All Media Folders Manage Media For Others Manage Own Media These permissions allow administrator users to be able to manage the content of other user's media folders but can restrict others to manage just their folders. Users with the Editor role can only see and manage their own media folder. Note that this is just about managing media assets not hiding the files of the folder. Every user can see the image served under the https://localhost:44300/media/_Users/4dsckq969tr2czhkskgg9nw3mj/image.jpg but they cannot delete this file and cannot modify the content of the 4dsckq969tr2czhkskgg9nw3mj folder. On the left window, the administrator user can see all of the folders, but on the right window, an editor user can only see their folder. If you don't like the naming _Users for the folder under AssetsPath, you can easily use another name for that just by using the appsettings.json file to configure media. If you navigate to Configuration -> Media -> Media Options you will find the name for the Assets user folder as well. Liquid IntelliSense for Monaco editor We have several custom Liquid filters and tags in Orchard Core and when you would like to use these from the admin UI of Orchard Core, (like editing a template or an Html Field using the Monaco editor) that would be nice to have some help with the registered filters and tags. This feature is about adding IntelliSense for Liquid in the Monaco editor. Let's see how we can try it out! Here we have a site installed with the Agency recipe. That recipe contains a Content__LandingPage template for the Landing Page content type by default. If we start to type the {% shape %} expression, we will see a list that contains all the registered filters with the word shape in it. Flow alignment icon always render as left aligned Let's say we have a content type with a Flow Part attached. If you are using Flow Part, you have the option to put several widgets to it. You can also set the alignments of the widgets and the width of the widgets meaning you can put two widgets near each other and you can say that I want to put this widget on the left side of the row and fill the 66% of the row with it and I want to put this widget on the right side of the row and fill the 33% of the row with it. You can do that using a nice UI but there was a minor bug which was about the little icon of the editor wasn't reflect the alignment of the given widget. You can see that now the icon here shows that the second Html widget inside the Container widget is right-aligned. News from the community A new website using Orchard Core: City of Santa Monica Santa Monica is a beachside city of 8.3 square miles on the westside of Los Angeles County. Offering an environment of unparalleled natural beauty, the city is home to a mix of residential communities, commercial districts, and recreational venues. And now the website of the City of Santa Monica is here, built by using Orchard Core! Check out this brand new, amazing-looking Orchard Core site here! If you are interested in more websites using Orchard and Orchard Core, don't forget to visit Show Orchard. Show Orchard is a website for showing representative Orchard CMS (and now Orchard Core) websites all around the internet. 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. DotNest Core DotNest Core is a complete redevelopment of the DotNest platform, all on the latest version of Orchard Core. We've been running it with a couple of select few customers for a while now, and it's time to open it up a bit more. While you can't yet just simply create an Orchard Core-based DotNest site, you can sign up for our limited beta here. You'll soon be able to get a fully functional, reliably hosted Orchard Core site on DotNest where you can build your personal website or something to showcase your Orchard skills with. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 216 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 Orchard meeting!

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

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

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

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

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

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