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

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

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

Latest tutorials

Featured tags

IIS
API
SMS
SEO
MCP
All tags >

Cors, user account activation - This week in Orchard (31/01/2020)

This week we would like to show you two new Orchard Core demos: the user account activation and the new CORS module. But before that let's take a quick look at the newest features and improvements of Orchard Core! Finally, let's see what about the next Harvest? Orchard Core updates Add more Resources documentation The Resources page of the Orchard Core documentation has been improved a lot. Now on this page, you can find examples about how to register a named resource by implementing the IResourceManifestProvider interface, how to render your registered resources in the different sections of the page using Liquid or Razor and many more! Update the OpenID YesSql stores to execute a concurrency check on updates We have a new feature in YesSql when saving a session. Check out the following line: _session.Save(application, checkConcurrency: true); In the code snippet above, we would like to save the Open ID application and check that nothing has changed the application between it was loaded in this process and saved with the current changes. And if there is an issue, it will throw an exception when we call await _session.CommitAsync(). Then it will catch the ConcurrencyException saying something else changed the application while you were saving it so, please try it again. Fix issue with layers that can be drag and dropped to zones The targets for the zone dragging were too loose and then you could drag a widget to a layer or a layer to a widget. Now it's fixed. Fix regression for Tag Helpers not working There was an issue that some things were working in development mode and not in release mode. In development, Orchard Core finds the Tag Helpers because views are compiled at run time in the context of the application, while published .Views.dll files have been precompiled in the context of their related module or theme. In production, it will not work, because for example if you would like to use the ContentItemTagHelper, the reference was missing from one module to the OrchardCore.Contents module. Dean Marcussen created a new OrchardCore.Contents.TagHelpers project, that contains the Tag Helpers of the OrchardCore.Contents module. And now whenever we have Tag Helpers, we put them in their *.TagHelpers library. So, when our themes and other modules will need those Tag Helper, we can just reference this library and not the full module. In the _ViewImports.cshtml files where we are using the OrchardCore.Contents assembly to find Tag Helpers we need to look for the assembly named OrchardCore.Contents.TagHelpers. It should not break any websites if you are using Liquid, but if you are not using Liquid, it's possible that the site will be broke after this change, meaning the Tag Helpers won't be found and as we said, you need to change your _ViewImports.cshtml. In the future, we have to do the same for all of the Tag Helpers. Standard display option for each field If you want to add a Display option for a field that does not have a standard one, when you re-edit the settings and save, the new one will be selected as the default even if you don't want it. To solve this issue we added a Standard option for all the fields. Let's see the HtmlField.DisplayOption.cshtml file as an example. Sort Workflow instances Your Workflow could have several Workflow instances and if you have many of them, it could be hard to find the one you want. In the past, you had the option to filter the instances by their status (all, faulted, finished), and now there is a new option to sort these instances. You can sort them by the recently created or the least recently created. Simplify part settings retrieval for ContentPartDisplayDrivers In the ContentPartDisplayDrivers, we need to resolve the ContentDefinitionManager, query the type definition and then find the part that is named the same that we are using, take the first one and get the settings. But in the BuildPartEditorContext and UpdatePartEditorContext we already have the TypePartDefinition of the part that we are currently editing, so we can just get the settings from there. This change made the code simpler and technically faster. Just take a look at the changes in the AutoroutePartDisplay! Demos User Account Activation Currently, Orchard Core supports registration and approval or manual entry. What about having a way to have the option to invite users onto the platform and let them choose their password and then activate their account? Let's see a possible future release for this feature! Install your site and then enable the Users Registration feature. Now head to Security -> Settings -> Registration, where you will find a new option: Administrators can send an activation email to a user. Put a tick in this box and select the AllowRegistration from the select list. Now go to Security -> Users and hit the Add User button. Here you could see a new switch called Send Activation Email?. If you create this user with this switch enabled and hit Save, this user will get an email that email will contain an activation link. If the user clicks on this link, they can choose a password for the account. After they set the password their account is activated and they can log in to the site using the newly created password. To do that, you should disable the account of the user when creating it. But what's behind this feature? Create two new Workflows to send emails. Let's call the first one to UserAccountActivation and add the Account Activation event as the startup event for this Workflow. Then add a Send Email task that will send the email to the user. This email will contain the activation URL of the user. Create another Workflow that will send another email that tells the user that their account is activated. Let's call this Workflow UserAccountActivated. Here you could use the Account Activated event as the startup event and again, add a Send Email task. The feature will be improved in the future because as you can see, the Send Activation Email switch is not really about sending an email, it's just about rising an event, that you can use in your Workflows. Instead of this, we could have for example a user state (Needs Activation) similar to the IsDisabled switch. And that's not all! If you would like to know more about this feature, head to YouTube, where you can find the full demo about the user account activation! Cross-Origin Resource Sharing (CORS) module If you head to Configuration -> Features and enable the Cors Configuration module, you will find a new option under Configuration -> Settings, called Cors. If you navigate here you can add as many policies as you want using the Add a policy button. On this page, you can add the name of the policy, set that as the default policy and configure everything that you will need to enable CORS. If you are interested in the full demo, don't forget to check out the recording on YouTube! News from the community The possible date of the next Harvest We had two possible dates for the next Harvest: one in February and one in April. Now it looks like it won't happen in February, so the only option left is to do a Harvest in April. The possible days could be between 13 and 17 in April. We also have two possible locations, which are Nice and Miami. Stay tuned for more information about the next Harvest! Tell us about your .NET performance challenges! - Hastlayer developer survey Help us build the nerdiest .NET thing, Hastlayer: It turns performance-critical sections of .NET programs into computer chips! If you fill out our short questionnaire you can win a cool compute accelerator board worth $265! Check it out here: https://forms.office.com/Pages/ResponsePage.aspx?id=Wt6elek45kStyIVVO-uCIMkFNjqW2E1Pm4v3YMcflMNUOVlDNUE3MlpDS044VDI1OEFSMUgxUkxSTC4u The reason we're asking this is that we're building a .NET hardware accelerator, Hastlayer (https://github.com/Lombiq/Hastlayer-SDK it turns your program into a chip!) and want to better understand what other developers do. Thank you in advance! Orchard Dojo Newsletter Now we have 114 subscribers of the Lombiq's Orchard Dojo Newsletter! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

Sitemaps, headless recipe, jsonparse Liquid filter - This week in Orchard (24/01/2020)

With many more features and updates, this week we check out the new headless recipe, the new jsonparse Liquid filter and the updates of the Orchard Core documentation. We show you a demo about the Sitemaps feature and write about when to ship version 1.0 of Orchard Core! Orchard Core updates Add Headless recipe Now you can find a new recipe called Headless. This is a new setup recipe that sets up a headless site that consists of CMS modules with GraphQL and OpenID. If you want to build a headless site, you will need to set up your site using this recipe. By the past, we were suggesting users do an empty site using the Blank recipe (empty.recipe.json) and then to enable OpenID and the needed modules. By using this recipe these modules are enabled by default. If you haven't seen it yet: there is a great detailed demo on YouTube about what will you get if you install your site using the Headless recipe. Documentation for recipes and starter themes included with Orchard Core Orchard Core is available for use via two different NuGet meta-packages: OrchardCore.Application.Cms.Core.Targets OrchardCore.Application.Cms.Targets You can also use several built-in themes: The Blog theme The Admin theme The Agency theme The Coming Soon theme The Theme And choose from different kind of recipes: Empty recipe Blog recipe Headless recipe Agency recipe Coming Soon recipe Saas recipe These themes and recipes include different configurations, different range of Content Types, Widgets and so on. There is a new getting started guide that lists what will you get if you install your site with one of the built-in recipes. If you are new to Orchard Core this guide will help you a lot to choose the recipe that fits the best for you. Fix previewing When you preview a content item we create a transient content item in the server-side memory and then we asked it to be rendered. Then we send the rendering to the client. That's how the preview feature works. Every time when you do a keystroke, we fake like it's a real content item, ask the server to create it in memory and to render it in HTML and send us back by the HTML. The issue was when we create it on the server-side it's like a real creation including indexing. Lucene will be like: there is a new content item to index, so let's index it! And then it will appear in the index, but it's just a preview. The idea is to find a way to mark it. A possible solution is to check the ID of the content item and if it's -1 (it's a logical value that we set for the content item to say it's transient), it's not a real content item, so just ignore it. Update "Creating a modular ASP.NET Core application" guide The section called Registering a custom route in the Creating a modular ASP.NET Core application is out of date with code generation templates and implementation since the upgrade to .Net Core 3.0. Generation templates create a Configure() method which accepts an IEndpointRouteBuilder (formerly IRouteBuilder), which does not have a MapAreaRoute() method. MapAreaControllerRoute() is the method to use here. Get draft content item by the alias Before we just indexed the published version of the aliases. If you are following the Creating a new decoupled CMS Website guide it tells you how to get a preview of a content item using an alias in a custom Razor Page. The issue is that it would not work if you were creating a new item and then previewing it, because there would be no published version of the content item, so it would not be able to find the content item by its alias. Now we are indexing the alias for both for the latest and published versions of a content item. The latest version can be the published one if there is no draft. Add jsonparse Liquid filter Let's say you would like to be able to pass a custom JSON using Liquid. Before that, we have to create a string separated by commas and then split it and then you will have an array. And then do it for each property you want, because you wanted to generate tables based on existing values you had. In the documentation, you can see an array of objects captured to a variable named someCollection. Using that, someCollection becomes a string variable that contains that JSON document. By calling the jsonparse using the someCollection you will get a JObject and then it can be iterated on and accessed by the key and value properties. This filter is enabled by default when you do Liquid. When to ship Orchard Core 1.0? We have issues labeled with P0 and P1. These issues should be fixed to ship version 1.0. We can't ship the new version without fixing these issues. The more the community works on these ones, the quicker we can release 1.0. Feel free to grab from these to be able to release sooner! Demos Sitemaps module revisited Let's set up a site using the Blog recipe. Then head to Configuration - > Features and enable the Sitemaps module. To use this module you need to set up the Base URL of your site under Configuration -> Settings -> General. After you have typed a fully qualified base URL of the web site, head to Configuration again, where you will see a new submenu called Sitemaps with two options: Sitemaps and Sitemap Index. Choose the Sitemaps one and click on the Add Sitemap button. Here you can see an Enabled checkbox, that gives you the ability to enable or disable your sitemap. If you uncheck this, you can disable the routing to the sitemap. If you are in the middle of constructing your sitemap or you don't want to publish it for some reason, you can uncheck this box. Give your sitemap a likable name and hit Create. Now you can add sources to your sitemap using the Add Source button. Here you can add Sitemap content types, that are entries for each one of the selected content types. Here you have the possibility to index all content types or just the selected ones. You can also limit the number of content items to provide from this source. Let's say we want to include the first 50000 blog posts to this sitemap source. After you hit Save, you can view your sitemap. To create a sitemap index, select the Sitemap Index option. Here you can set the URL of the sitemap index and the sitemaps this index contains. We have only one sitemap, so, select that one. When you enabled the Sitemaps feature, you could see another related one in the Features list, called Localized Content Items Sitemaps. If you enable this module and have localized content items, you can build localized content items sitemaps. Let's see how a sitemap like this looks like! Here you can see the language of the given content item inside the hreflang elements of the XHTML tags. The content with the primary culture of your site goes first, which is en-US in this case. In the screen below you can see a sitemap that contains one blog post, that has a Hungarian localization too. And that's not all! If you would like to know more about sitemaps, head to YouTube, where you can find the full demo about sitemaps! This feature is still under development, but you can check the PR here. News from the community Tell us about your .NET performance challenges! - Hastlayer developer survey Help us build the nerdiest .NET thing, Hastlayer: It turns performance-critical sections of .NET programs into computer chips! If you fill out our short questionnaire you can win a cool compute accelerator board worth $265! Check it out here: https://forms.office.com/Pages/ResponsePage.aspx?id=Wt6elek45kStyIVVO-uCIMkFNjqW2E1Pm4v3YMcflMNUOVlDNUE3MlpDS044VDI1OEFSMUgxUkxSTC4u The reason we're asking this is that we're building a .NET hardware accelerator, Hastlayer (https://github.com/Lombiq/Hastlayer-SDK it turns your program into a chip!) and want to better understand what other developers do. Thank you in advance! Orchard Dojo Newsletter Now we have 113 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!

Sortable lists, IScopedDistributedCache - This week in Orchard (17/01/2020)

Get ready for a deep dive! In our post, we will introduce the IScopedDitributedCache service and show how to use it in the RoleStore. And we are going to solve the mystery about do you need the Model prefix to access different kinds of properties of a model in Liquid and in Razor too? Orchard Core updates Document recipes new Lucene settings There is new documentation on the updated Lucene index settings. Now to create an index from a recipe, it's not just about passing the name of the analyzer. You have to provide the following: AnalyzerName: the name of the analyzer, that you want to use. IndexLatest: a boolean value that indicates that if you want to index the latest or just the published versions. IndexedContentTypes: the list of types you want to index. Re-use in some places the ContentItem Liquid property There was a change in the Liquid TemplateContext, that broke some properties, that are available in the templates. If your AliasPart, AutoroutePart or Workflows patterns don't work anymore, it's because of the previous change. Now, this issue has been fixed. For example in an Autoroute pattern that used to render the custom URL of the content type you could do something like: {{ ContentItem.DisplayText | slugify }} That will generate a nice text for your routes. But in some cases, you have to write {{ Model.ContentItem.DisplayText | slugify }}. Maybe using the Model prefix is collateral damage, but maybe it has a purpose. Anytime we have a Liquid template for a shape we do Model.ContentItem to get the ContentItem. In Razor everything is Model.Something. It has to be because in Razor we are doing C# and the current context is the page and the page is a class that doesn't have our properties like @ContentItem. So the only thing we could get is the @Model that is typed to the generic type of the RazorPage and Model will provide all the properties like the ContentItem. Because we do too much Razor, it could be possible that we reused this approach into some Liquid patterns. In Liquid it's not necessary to have the Model prefix. But it appears that there is already a way in Fluid to use a first-level model without a custom prefix (so we don't need a Model prefix), by setting the TemplateContext.Model property. In conclusion: in Liquid that is easier to write {{ ContentItem.DisplayText }}, you don't need the Model prefix. But in Razor, you have to use the Model prefix. Constraint admin controllers to mapped routes Since we can change the prefix of the admin route, we have to ensure that every admin controller's actions have the correct prefix to use. There is an implementation of the IActionConstraint, called AdminActionConstraint, that checks if we are in the admin and the route doesn't start with the admin URL prefix (_adminUrlPrefix), then it will create a warning log entry. So, the AdminActionConstraint applies a convention that restraints all AdminControllers or [Admin] controllers to use the mapped route only, and not the default route applied by MVC. Fix the recipes not found bug in the documentation We have a guide about how to create a new decoupled CMS Website using Orchard Core. It told you to add the OrchardCore.Application.Cms.Core.Targets NuGet package to your new ASP.NET Core project, because this package won't contain the themes. And when you do a decoupled CMS site you will don't need the themes, because you want to create your own front end. The issue is with this package on the master branch is that the setup doesn't contain any recipe in the RC1 version. The community fixed that bug for now, but it's just in the dev branch yet. So, if you follow the guide and you using the RC1 version of that package, when you arrive at the setup screen you will not be able to set up the site because there will be no recipe to choose from. Mitigation is to use the OrchardCore.Application.Cms.Targets package, that contains all the themes and recipes. Of course, in this case, you will get several unwanted themes, but you will not be blocked to continue following the guide. So, it's not the perfect solution, but when there will be a new version of Orchard Core, we can rewrite this back to use the OrchardCore.Application.Cms.Core.Targets NuGet. There is also a hint about if you are using the nightly builds of Orchard Core then you should use the Core package instead. Creating IScopedDitributedCache The main goal is to increase the performance of Orchard Core and try to make it faster from time to time. To measure that, check the blog posts Liquid template page and start to remove everything from there. Just to see how fast could be the performance if we didn't render anything. Then start to remove stuff from the controller that displays content. For example, let's take a look at the ItemController. This is the controller, that renders content items by default. Take a closer look at the Display method of this controller! It first loads the content item. If it's not there, we return a 404. Then we check the ViewContent permission for this content item for the current user. We return Forbid if they authenticated but don't have the proper permission, or return Challange if the user is anonymous. Now let's build the display! That will build a shape containing all the part shapes and everything for this content item. So, it will render the display of this content item and we send this shape to a view that will just call Display of the shape. That's what we do in this method. The thing that made it slow actually is that one which checks the permissions, the _authorizationService.AuthorizeAsync. The user is anonymous and checking that the anonymous users could see something was the bottleneck of the performance. For each display of the site, there would be a database query just to authorize the anonymous user to be able to see something. This is actually a regression. Once you remove this code the controller will be much faster. An authenticated user would have added Claims cached in the User object. But in the case of an anonymous user, nothing was cached. Each request for an anonymous user would ask the permission for the anonymous user from the RoleStore. The RoleStore would do a query all the time. There is a new service, called ScopedDistributedCache. The idea is to use a distributed cache, such that we would store the Roles document in memory if we have a single node or in a store that is shared across every node if you have multiple nodes. Scoped means if you do multiple queries on the same cache entry for the same request, then we will load it from the DistributedCache only once. That will be much faster if you have multiple queries. You can see the usage of the ScopedDistributedCache in the RoleStore. Instead of injecting the IMemoryCache (that puts everything in the memory that shared by all the request) here comes the IScopedDitributedCache. The code is much simpler with that: you just pass it an object. Check the GetRolesAsync and the UpdateRolesAsync methods of the RoleStore. Demos Make lists sortable with ordering setting Let's say you have a site that you set up using the Blog recipe. In that recipe you can find a Blog content type, that is used as a container of the Blog Post content items. To behave the Blog content type this way, you need to add the ListPart to it, which will add the list behavior. Here you could see a new option before the Contained Content Types list, called Enable Ordering. If you check this option you will enable the manual ordering of the items. Let's put a tick here! Now head to the Content -> Content Items page and select the one named Blog (or just simply hit Blog from the menu). Here you can see the list of the blog posts contained in this blog content item. Let's add more posts to it to see the power of this new feature! By using a simple drag and drop, you can set the order of the different items and save it on the fly. Check out the following GIF to see how the reordering works! This feature is under development, but you can find the code in this pull request. And don't forget to watch the recording about this demo, where you can also hear an informative discussion about some interesting questions to solve, for example, what about reordering content items that have a published and a draft version too? News from the community New Orchard Core site: Buzz Interactive Buzz believes that great digital products are built on intelligent strategy and outstanding technical abilities. They partner with vibrant clients and help them create future-proof platforms for web, app, and VR. And they use Orchard Core for their site! 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. Tell us about your .NET performance challenges! - Hastlayer developer survey Help us build the nerdiest .NET thing, Hastlayer: It turns performance-critical sections of .NET programs into computer chips! If you fill out our short questionnaire you can win a cool compute accelerator board worth $265! Check it out here: https://forms.office.com/Pages/ResponsePage.aspx?id=Wt6elek45kStyIVVO-uCIMkFNjqW2E1Pm4v3YMcflMNUOVlDNUE3MlpDS044VDI1OEFSMUgxUkxSTC4u The reason we're asking this is that we're building a .NET hardware accelerator, Hastlayer (https://github.com/Lombiq/Hastlayer-SDK it turns your program into a chip!) and want to better understand what other developers do. Thank you in advance! Orchard Dojo Newsletter Now we have 113 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!

ConsoleLog helper, IsSectionDefined method - This week in Orchard (03/01/2020)

Happy new year everyone! There was no meeting this week, but in the first post of 2020, we would like to give you a nice overview of the latest improvements of Orchard Core, including the ConsoleLog helper, updated documentation, the new look and feel of our weekly blog post and newsletter and many more! Orchard Core updates ConsoleLog Razor helper and Liquid filter Sometimes you may struggle to get the correct placement or the available alternates of a shape. From now there is a shape dumper to try and see what was going on. Dean Marcussen adapted the dumper to use the ConsoleLog, so when you dump ZoneHolding, you see the holding zone, then another log with all the items in it, with their alternates (as they are calculated at execution time). Let's say you rewrite the Content-BlogPost.liquid to Content-BlogPost.cshtml. In this case, you can use the ConsoleLog Razor helper in the following way: @Orchard.ConsoleLog((object)Model) Then hit F12 if you are using Google Chrome and check the content of the console. The ConsoleLog extension method can be used to dump data from well-known properties, or objects serializable to JSON to the browser console. But if you prefer Liquid instead of Razor, you can use the console_log Liquid filter that will do the same for you in Liquid! Check out the documentation for more info about these new features! Thanks to this new shape dump feature you can construct your Orchard Core site faster and easier! Register User class as an accessible Liquid member Let's say you want to get the User fields from a Liquid template when you are using the UserCreated event of a Workflow. To do that, it's required to make this class an available one from Liquid. Else the only value accessible is the Workflow.Input.User which returns the username. If you check the content of the UserLiquidTemplateEventHandler class, you will see that the User class has been registered. Handle error while rendering resources When using the ResourcesTagHelper and referencing a non-existing resource, it breaks page rendering with the following error: Error 500 : InvalidOperationException: Could not find a resource of type 'X' named 'Y' with version 'Z'. It should log an error, but not break the rendering. To do not break the rendering, the Process method of the ResourcesTagHelper now catches the exception if any and creates a log entry instead of breaking the rendering. Clarify getting started and update for .NET Core 3 in the documentation The Getting Started page of the documentation is one of the most important parts of the Orchard Core documentation where you can see how you can add the Orchard Core NuGet packages to your .NET Core web application. Now this page got some more details about how to create your empty .NET Core web application, how to use the dev packages of Orchard Core and so on. Cloning removed LocalizationSet When cloning a content item that has a LocalizationSet, a duplicate entry of a language was created. That's because the LocalizationSet was not being cleared when cloning so a duplicate entry would be created for a locale. The fix was to remove the LocalizationSet when cloning in the CloningAsync method of the LocalizationPartHandler. Here you can see that the LocalizationSet of the cloned part will get an empty string value. Added IsSectionDefined method Let's say you are using RenderSection to render a zone in a view and you want to render certain HTML elements before and after rendering the zone, only if the zone is available. First, you can call IsSectionDefined to verify if the zone is present as follows: @if (IsSectionDefined("News")){ <div class="news"> @await RenderSectionAsync("News", required: false) </div>} But it was throwing the following exception. InvalidOperationException: IsSectionDefined invocation in '/Areas/XXX/Views/XXX.cshtml' is invalid. IsSectionDefined can only be called from a layout page. The fix for this issue was to add the IsSectionDefined method to the RazorPage abstract class. News from the community Improving our This week in Orchard newsletter We published our first This week in Orchard post on the 20th of June, 2018 and since then we wrote 75 posts, 76 with this one :). Our goal is with the series is to give you valuable news and demos about the happenings around Orchard and Orchard Core every week. To do it we improve the posts from time to time and from this year we would like to introduce a new pack of changesets. Last month we created a poll on Twitter and asked you: would you like keywords about highlights in the title of This week in Orchard blog posts and newsletter subjects? We had 10 votes and everyone agreed that this would help to search, so from now, we changed the title in this way. And that's not everything about the title. Regarding the current date, we used the following format: mm/dd/yyyy. From this year we will use the following format: dd/mm/yyyy, which is a more international way to represent the date. We also changed the structure of the posts a little bit. Let's see the old way: On Orchard 1.x: contained everything that is related to Orchard 1.x. On Orchard Core: contained everything that is related to Orchard Core like the new features, bug fixes, new websites built with Orchard Core. Demos: this section was inside the On Orchard Core section and contained demos about Orchard Core. If there were demos about Orchard 1.x, the On Orchard 1.x also had this section. On Lombiq: news from Lombiq. And now let's see the structure that we use from this year: On Orchard 1.x: new features and news around Orchard 1.x, but the demos will be in a separate place together with Orchard Core demos. Orchard Core updates: bug fixes, new features of Orchard Core. Demos: here come the demos of Orchard 1.x and Orchard Core. News from the community: new websites, news about the Harvest, blog posts about Orchard Core, news from Lombiq, everything that is not related to the code itself. And if you are subscribed to our newsletter you will see that we created a new template for our emails that looks nicer and easier to read. We hope you will like our improvements! Feel free to contact us and share your thoughts about the current improvements or add your own ideas that could help us to make This week in Orchard better! Orchard Dojo Newsletter Now we have 112 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!

This week in Orchard - 11/01/2019

Do you remember the Nwazet Commerce module for Orchard 1.x? Orchard Core Commerce will be the Orchard Core port of that module and this week we will see the current state of this module! But first, take a look at the new structure for the documentation and the other improvements of Orchard Core! On Orchard Core The new structure for documentation When you navigate to the Read The Docs site to check the documentation of Orchard Core, you will meet with a brand new structure. All the previous docs are under the Reference menu on the top. Here you can see all the modules and their reference documentation. The Key Topics are just explaining core concepts. Explore the new documentation now! Add culture argument to localization_set filter This adds an argument for culture in the localization_set filter and defaults to current culture if there are no arguments. {{ Model.ContentItem.Content.LocalizationPart.LocalizationSet | localization_set: "en" }} New ContentCard Shape to make Flow Editor extensible Now the ContentCard shapes have been merged to the dev branch of Orchard Core, so you can use this awesome feature! But why ContentCard Shape Needed? Every widget within FlowPart, BagPart, and WidgetsListPart has Bootstrap card with similar UI which can be dragged or deleted. Unfortunately, these parts add hard-coded alternate for widget editor Widget_Edit__Flow, Widget_Edit__Bag, and Widget_Edit__List just before DisplayAsync hence - none of the custom alternate defined in admin theme for the widget is applied i.e. Widget-WeatherWidget.Edit.liquid (Widget_Edit__WeatherWidget). Due to hard-coded alternates, none of the placement customizations on Content_Edit applies to Flow editor. i.e. having AdminTab in Flow editor. All widgets are framed with a <div> tag, with no ability to customize. This limits the usability of the Form module and makes very cumbersome to create complex forms. FlowPart, BagPart, WidgetsListPart has the advantage of the free flow page but did not come even close to the usability of Layout in Orchard 1.x and Layout Template. Orchard DisplayMangement is powerful but FlowPart, BagPart, WidgetsListPart not utilizing it to make it extensible. These parts render cards using a hard-coded widget template in javascript, which doesn't honor shape alternates. How ContentCard Shape Helps? Doesn't add any alternates to Content Editor, hence any edit alternates defined for a widget will be displayed in Flow editor. Because it's using Orchard DisplayMangement, that means all placement details are applied including Admin Tabs within Flow editor. Defines ContentCard_Frame shape and list of alternates that module developers can override in Module or Admin Theme. Ability to disable, move or delete the Widgets to create Orchard 1.x like Layout Template. Ability to control, expand or collapse by a developer in Module/Admin Theme. Rendered 100% from a shape, not using an HTML template inside Javascript. Uses ShapeTableProvider to define alternates. Orchard 1.x layout like UI created with ContentCard shape, using some ContentTypes in BagPart and creating alternates only for ContentCard_Frame shape. Just check out to the dev branch to try out the new editing experience right now! Add configuration section to setup docs You can set up your site by providing the configuration parameters via the appsettings.json file. The documentation has been improved with the correct way you can do that. Default pattern for autoroute and alias When we add an Alias Part or an Autoroute Part, we don't have to go to the Settings, it will now use a standard pattern. public class AliasPartSettings{ [DefaultValue("{{ ContentItem.DisplayText | slugify }}")] public string Pattern { get; set; } = "{{ ContentItem.DisplayText | slugify }}";} Demos Orchard Core Commerce module Orchard Core Commerce will be an Orchard Core port and partial rewrite of the open source Nwazet Commerce module that was built for Orchard 1.x. Nwazet Commerce was initially built in 2012 by Bertrand Le Roy, loosely based on a commerce sample by Sipke Shoorstra. Now let's see the current state of this module because there are features that you can already try out! First, set up your dev environment: Download/clone the module from GitHub. Place it under the src/OrchardCore.Modules folder. Add the existing project to the solution under src/OrchardCore.Modules in the solution explorer if you're using Visual Studio. Add a reference to the module from the OrchardCore.Cms.Web project. If you are ready, build and run the solution. We set up the site using the Agency recipe for this demo. Now head to Configuration/Features in the admin, where you have to see the following modules. Enable both of them! Orchard Core Commerce: Registers the core components used by the Commerce features. Orchard Core Commerce Session Cart Storage: Registers session-based shopping cart persistence. In OrchardCore.Commerce any content type can be a product. It's just the manner of having the Product Part attached to your content type. This part identifies any content item as a product, by its mere presence. It has only an SKU, that describes the most basic product attribute, which can also be used as an alias for the item. You will also find a new Price Part, that just a simple product price that stores the price of the product. There is also the notion of Product Attribute Field, which adds the ability for a product to be modified with a set of attributes, in particular when added to a shopping cart. Examples of attributes can be shirt sizes (S, M, L, XL), dimensions, etc. Now let's try these out! Let's say we would like to sell T-shirts in our shop. Create a new content type called T-shirt and add the Title, Common, HtmlBody, Product and Price parts to it. Every product could have different fields, in our case, we will need a size, a message printed on the T-shirt and the color of the T-shirt. Let's add these fields to our content type using the Text Product Attribute Field type. You can add some predefined values to size and to colors and restrict them. Now let's create a new T-shirt, give it a name and some description and hit Preview. Here you can see that the users can customize their product using our fields. They can set the size, the quantity, the message, and the color. And at the bottom of the screen, you could see an Add to cart button. Let's fill out these fields and click on this button! We selected one black T-shirt with a size L and with a custom message. You can update the quantity here that will update the price if you click on the Update button or remove the product from the cart with the Remove button. So, for now, the following features are done: Product, price, and inventory parts and/or fields (those were a single part in Nwazet) Note: not all products have a price Shopping cart To do: Checkout (probably redesigned around Orchard Workflows) Base infrastructure for payment, plus one implementation (Stripe) Order content type and management screens (including a redesign and refactoring of the order part) Workflow activities On Lombiq Searching for performance-intensive codes Do you write a performance-intensive code? Then help us build the nerdiest .NET thing! Drop us a line to [email protected] and we'll ask a few questions about the challenges you encounter, and in exchange, we'll show you how to make a chip out of your programs! Orchard in Open Academy There will be the free Open Academy in Budapest on 22 November for all life long learning developers with no-BS tech talks, where Zoltán Lehóczky, the Co-founder and managing director of Lombiq Technologies Ltd. will talk about Orchard. Come and join the conference if you will be nearby! This week in Orchard in LinkedIn From now you could find our This week in Orchard series on LinkedIn, under the Lombiq Technologies Ltd. company account! Share and like these posts there too if you are learning something new reading our weekly recaps! Orchard Dojo Newsletter Now we have 101 subscribers of the Lombiq's Orchard Dojo Newsletter! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

This week in Orchard - 10/25/2019

This week we are coming with a cool demo of presenting the newest improvements of an upcoming Orchard Core module that will add sitemaps to your site! But first, don't forget to check the documentation of Orchard Core, we have a lot of additional lines here! On Orchard Core Updating OpenId docs about how to use the certificate on Azure When you would like to enable authentication of external applications using the OpenID Connect/OAuth 2.0 standards, you have to configure the certificates too. You can generate and store your certificate on Windows and/or IIS, but you can also upload the certificate on an Azure hosted site. This little addition to the docs will help you with that. CommitTransactionTask workflow activity When you have two concurrent updates that depend on each other, you need to commit the previous transaction, that you can follow up with the next one and the first one can continue and get another one. So, when you have two nested transactions to each other, you could create a deadlock, that is very specific to SQLite. Now there is a new Task available when you are creating workflows. The CommitTransaction activity is about committing the current transaction by calling the CommitAsync method of the ISession implementation. Add OrchardCore.Email docs We have the OrchardCore.Email module, that allows you to send emails using SMTP. You can configure the settings for this module by using the appsettings.json file. Now you will find documentation about how you need to fill this JSON file and also with some description about the meaning of the values. Add role description Now you can provide a description of a role when you are creating a new one or editing an existing one. It will make your life easier in the future if you have more roles and want to stores what are the current roles used for. Now we have documentation about what are the predefined roles used for and how to configure the roles through a recipe step. Four Orchard Core samples for Orchard Core Dody Gunawinata maintains a repository in GitHub that contains 305 samples for ASP.NET Core with projects about how to use Blazor, foundational ASP.NET Core samples and so on. This repository also contains 4 samples that show the different capabilities of Orchard Core. These are: Routing - MVC: This sample shows how routing works in an Orchard Core Framework app. Routing - Razor Pages: This sample shows how routing works in an Orchard Core Framework app when you are using Razor Pages. Static files: This sample shows how to use static files in the module. Multi tenant: This sample shows how Orchard Core Framework handles multi tenancy and how each tenant has its own configuration file. If you are interested in these samples or other ASP.NET Core samples you should definitely check this great and huge collection to learn something new! Scanning the code of Orchard Core for bugs PVS-Studio performs static code analysis and generates a report that helps a programmer find and fix bugs. PVS-Studio performs a wide range of code checks, and it is also useful in finding misprints and Copy-Paste errors. The authors of this project published an article about reviewing the results of a second check of the Orchard Core with this static analyzer. The current version of Orchard Core is made up of 2,767 .cs files, i.e. it's about one thousand files smaller. The downsizing and renaming of the repository suggest that the developers have isolated the project's core (commit 966), which is 108,287 LOC long. The analyzer issued 153 warnings: 33 first-level and 70 second-level ones. You should definitely check this article, you can learn a lot and write better code! Do you write a performance-intensive code? Then help us build the nerdiest .NET thing! Drop us a line to [email protected] and we'll ask a few questions about the challenges you encounter, and in exchange, we'll show you how to make a chip out of your programs. Demos Sitemaps module A few weeks ago we wrote about an upcoming module for Orchard Core: the Sitemaps module. Since then this feature improved a lot and will be released soon. Let's recap the latest changes of the module! First of all, when you navigate to the Configuration/Features on the admin site, you will see that there are three different Sitemaps modules: Sitemaps: Provides dynamic sitemap generation services. Sitemaps for Decoupled Razor Pages: Provides decoupled razor pages support for dynamic sitemap generation. Localized Content Item Sitemaps: Provides support for localized content item sitemaps. Let's check them one by one with a site that we set up using the Blog recipe. When you enable the Sitemaps module you can head to Configuration/Sitemaps and click on the Add Sitemap button. Here you will see two notions: the Sitemap Content Types, that add sitemap entries for each one of the selected content types and the Sitemap Index, which adds a sitemap index that acts as a container for other sitemaps. You can create a new Sitemap Content Type, that will lead you to a familiar page where you can select which content type you want to include in the index, among with the change frequency, priority and the number of content items to include. The other is called Sitemap Index. In the editor of the Sitemap Index, you can select which sitemap will this index contains. Because for now we have only one (called My Blog Posts) select this one. Hit Save and View this Sitemap Index. You can see that this index contains our only one sitemap with the last modified date of it and the location. By using sitemap indexes, you can provide a collection of sitemaps to search engines. For example, when using Google, all formats limit a single sitemap to 50MB (uncompressed) and 50,000 URLs. If you have more than 50,000 blog posts, you have to create two Sitemap Content Types. The first one will take the first 50,000 one and the second one is the rest. And your Sitemap Index will include these two Sitemap Content Types. Now let's move on and enable the Localized Content Item Sitemaps. To test this, first, attach the Localization Part to our Blog Post content type and create two blog posts, one in Hungarian and one in English. Now head back to the admin of the Sitemaps module and View our My Blog Posts Sitemap Content Type. You see that our sitemap provides more information to search engines. First of all, you can see that both the English and Hungarian versions of our blog post have been included in the sitemap. These come with the hreflang attribute. If you have multiple versions of a page for different languages or regions, tell Google about these different variations using the hreflang attribute. The loc is still used and that points to the version of the content item that was created using the default culture. Finally, enable the Sitemaps for Decoupled Razor Pages feature. For this, we will add a new content type, called DecoupledBlogPost. This content type will not have any parts or fields attached. To be able to provide a sitemap for decoupled Razor pages, first, configure the SitemapsRazorPagesOptions for our content type in the Startup.cs file of our module. services.Configure<SitemapsRazorPagesOptions>(options =>{ options.ConfigureContentType("DecoupledBlogPost", typeOptions => { typeOptions.PageName = "DBlogPost"; typeOptions.RouteValues = (contentItem) => { return new { area = "OrchardCore.Sitemaps", slug = contentItem.ContentItemId }; }; });}); Here you can see that a DBlogPost.cshtml file sits in the Pages folder and we just simply put this into the OrchardCore.Sitemaps module. We will pass the ContentItemId as a slug for our page. Now let's see the content of the Razor page: @page "/blogpost/{slug}"<h1>This is the blog post.</h1><h2>Slug: @Slug</h2>@functions{ [FromRoute] public string Slug { get; set; }} Now head back to the admin and create two new Decoupled Blog Post. After let's create a new Sitemap Content Type, called Decoupled Blog Posts, that will (surprisingly) index the Decoupled Blog Post content types. After you saved this sitemap, hit View! Here we are with the two Decoupled Blog Posts that have the ContentItemId in the URL. We haven't attached the Localization Part to this one, so the hreflang attribute will not be used here. Now open one of those blog posts! And here comes our decoupled blog post that is using The Blog Theme for rendering the content of this item. This feature is still under development and can be found in this branch. Big thanks again to Dean Marcussen for this great contribution! On Lombiq Lombiq Orchard Visual Studio Extension updated The Lombiq Orchard Visual Studion Extension just got some VS 2019 compatibility updates. There was a warning message that said One or more extensions were loaded using deprecated APIs. Check it out if you aren't using it already, you're missing out on quite some productivity boost! Orchard Dojo Newsletter Now we have 100 subscribers of the Lombiq's Orchard Dojo Newsletter! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

This week in Orchard - 10/18/2019

This week we are coming with a cool demo of using Statiq with custom GraphQL and Liquid modules to render static content for Orchard Core as a headless CMS! But before jumping to that don't forget to check out the other news around Orchard Core and another demo about adding the ability to generate DisplayText with a pattern! On Orchard Core Avoid slash in the role name The slash will add another segment that prevents to use from editing or deleting the role. Now we are checking that if the name of the role is containing a slash or not. If yes, you will see an error message. Decoupled CMS guide When you navigate to the Orchard Core Documentation page and hit the Index under the Guides in the left, you will see that we have a new tutorial here, called Building a decoupled website with Razor Pages. By following this step-by-step tutorial you can easily develop your own decoupled CMS site from the scratch. In this tutorial we learn how to: Start a new Orchard Core CMS project Create custom content types Edit content items Create Razor Pages with custom routes to render the content Load content items with different identifiers Render WYSIWYG preview screens while editing the content Add Breadcrumbs zone There is a new zone called Breadcrumbs in the layout of the admin. With that zone, we can inject breadcrumbs. Anywhere, where the breadcrumbs were used they are now using this zone, for example on the workflows page. There is a zone tag, so everything that is inside this zone tag will be injected inside the Breadcrumbs section. And here you can see the RenderSectionAsync call in the Layout.cshtml of TheAdmin theme. Updating themes All the themes that are using Bootstrap now have been updated to use the latest version. The main change is that all the static assets now are included in the themes, which means they can now be served by the Orchard instance and not just the CDN. And now each theme has a ResourceManifest, that defines all the assets that each theme is using, like jQuery, Bootstrap, Bootstrap bundle and so on. The local version and the CDN is also defined here, that allows these themes to reuse the settings that we set in the admin to select which version of the resources we want to use either local or CDN or based on the environment (meaning development will use local, production will use CDN). You can see a vendor- prefix in the names, it is to prevent conflicts with the resource names that we have defined in the OrchardCore.Resources module. Orchard Core Docs new structure The structure of the Orchard Core docs will be reorganizing and come with a new MkDocs theme. Here you can see just the material and here you can see the new structure that coming soon. Demos Add ability to generate DisplayText with a Pattern Let's set up a site using the Blog recipe. Now head to the admin site and edit one of the content types, for example, the Article. Add a new Text Field to it, let's use the Name for the Technical Name. Now edit the Title of the Article. Here you will see an Options drop-down list with the following options: Title is editable: you can edit the title when editing the content item. Title is generated and input is disabled: you can't edit the title and the textbox for the title is disabled. Title is generated and input is hidden: you can't edit the title and the textbox for the title is hidden. And under that, there is the pattern used to render the title of this content type. The pattern gets injected and this gets called when the content item is updated. Now let's edit the existing Article, called About and fill the Name Text Field with some value, for example Name. And change the value of the Subtitle Text Field to Subtitle. After hit Publish. Now if you navigate to Manage Content page you will see that the title of this Article has been generated using the values of the Name and the Subtitle Text Fields. Because at the content definition of the Title we select that the Title is generated and input is disabled, when you try to edit an existing article, you will see the disabled textbox for Title. Generating static sites using Statiq(Wyam) and Orchard Core If you haven't heard about Wyam(Statiq) yet, let's recap the underlying concepts first: Wyam is a simple to use, highly modular, and extremely configurable static content generator that can be used to generate web sites, produce documentation, create ebooks, and much more. Since everything is configured by chaining together flexible modules (that you can even write yourself), the only limits to what it can create are your imagination. Common static sites are using tools like Jekyll/Hugo which are based on content in markdown files, stored in GitHub. Some arguments: This might work for small and technical teams, but when users are more than a handful or don't have technical knowledge it's not possible anymore. When assets management is required, with organizing images or adding metadata. Rights management, such that sections of the site can only be modified by some users. Editing workflow, when content needs to be reviewed and pass different levels of validation. Allow more complex editing scenarios, like editing maps, choosing a color. Managing more than a dozen content items, like e-commerce sites that could span thousands of products. When online B2B communications are required, like export processes, tax data updates, or webhooks. Now let's see how to generate static sites! First, let's set up a site using the Blog recipe. Now head to the Configuration and enable the following OpenID modules: OpenID Authorization Server and OpenID Token Validation. We also need the GraphQL, so enable that module too. The goal is to implement the authentication from a service to the Orchard Core by using Bearer tokens and OpenID. With that, you can use the APIs from another service. After go to the Authorization server settings under OpenID Connect/Settings and allow the Client Credentials Flow. The OpenId Connect Client Credentials grant can be used for machine to machine authentication. In this grant a specific user is not authorized but rather the credentials are verified and a generic access_token is returned. Now create a new application under OpenID Connect/Management. This will be our service that will connect to the Orchard Core instance. Don't forget to allow the Client Credentials Flow here and of course, provide a Client Id and a Client Secret. We will need these soon. Now we have a configured Orchard Core instance to serve content to our application using GraphQL and the Client Credentials flow. For the sake of simplicity, we will create a Console Application. This application has to use the Client Credentials Grant Flow for authentication. curl -XPOST "https://<region>.onelogin.com/oidc/token" \-H "Authorization: Basic <base64 encoded client_id:client_secret>" \-H "Content-Type: application/x-www-form-urlencoded" \-d "grant_type=client_credentials" First, create a request on the /connect/token on the Orchard Core instance. Then create a Basic authentication header with the Client Id and the Client Secret. Remember you provided these data when setting up the OpenID application in Orchard Core. After we send the request and the response will be a JSON document with an access_token property. This property stores the value of the access token that we can use to send any request to the server as a Bearer token. Check this code snippet to receive this token. using (var httpClientHandler = new HttpClientHandler()){ httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; httpClientHandler.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate; using (var httpClient = new HttpClient(httpClientHandler)) { string accessToken; using (var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://localhost:44300/connect/token"))) { request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes("theclientid:theclientsecret"))); request.Content = new StringContent("grant_type=client_credentials"); request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); using (var response = await httpClient.SendAsync(request)) { var data = await response.Content.ReadAsStringAsync(); var doc = JsonDocument.Parse(data); accessToken = doc.RootElement.GetProperty("access_token").GetString(); } } }} And the value of the doc JsonDocument will be the following, where you can see the access token. {"token_type":"Bearer","access_token":"CfDJ8IFF_p0sw0lLjSdTpd..........cDRRiQXfpVZsHo","expires_in":3600} In the next step, we are creating a new Bearer token with the access token and we are pointing to the GraphQL endpoint with a query listing all the blog posts. With that, we can get all the blog posts. using (var request = new HttpRequestMessage(HttpMethod.Get, new Uri("https://localhost:44300/api/graphql?query=query%20MyQuery%20%7B%20blogPost%20%7B%20displayText%20markdownBody%20%7B%20html%20%7D%20%7D%20%7D"))){ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); using (var response = await httpClient.SendAsync(request)) { var data = await response.Content.ReadAsStringAsync(); Console.WriteLine(data); }} You can see that we pass the GraphQL query in the query string in an URL encoded format. Here is the query in a readable way: MyQuery { blogPost { displayText markdownBody { html } }} We use Console.WriteLine to see the data coming from Orchard Core. Because we set up our site using the Blog recipe and haven't added any additional blog posts, our response will be the following: So, this is how you do Client Credentials Flow to authenticate your application against Orchard Core. This is the first step needed to generate a static site. Now let's just refactor our code a little bit. Create a ClientCredentialsAuthenticate method to get the access token. With the ClientCredendialsAuthenticate method, we can do as many calls as we want. You can see the BlogPosts query that we will pass to a custom Statiq module called GraphQLQuery. This module will just take the GraphQL endpoint, the query, and the access token. We will also need to develop another custom module extension using Statiq, called Liquid module to be able to use Liquid. const string BlogPosts = @" MyQuery { blogPost { displayText markdownBody { html } } }";static async Task Main(string[] args){ var token = await GraphQlQuery.ClientCredendialsAuthenticate(new Uri("https://localhost:44300/connect/token"), "theclientid", "theclientsecret"); await Bootstrapper .CreateDefault(args) .BuildPipeline("Posts", builder => builder .WithInputModules(new GraphQLQuery("https://localhost:5001/api/graphql", BlogPosts, token)) .WithProcessModules( new SetDestination(Config.FromDocument(doc => new FilePath(doc.GetString("displayText") + ".html"))), new Liquid("templates/blogpost.liquid")) .WithOutputWriteFiles() ) .RunAsync();} For every blog post, it will apply the transformation, by getting the displayText property of the JSON document and create an HTML file based on that. After apply the Liquid filter based on the blogpost.liquid template, that has the following content: <h1>test</h1><p>{{ displayText }}</p>{{ markdownBody.html | raw }} If you run that application you will get one HTML file in the bin/Debug/netcoreapp3.0/output folder of your application called Man must explore, and this is exploration at its greatest.html. If you open the file you will see the following result. With that, you can go further and generate all the static sites you want based on GraphQL and use Razor or Liquid. On Lombiq Orchard Dojo Newsletter Now we have 98 subscribers of the Lombiq's Orchard Dojo Newsletter! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

This week in Orchard - 10/04/2019

The first release of Orchard Core RC shipped last week, but the community has already added several new great features and improvements to the CMS! In our post, we show you two demos about the flow improvements and the new Sitemaps module! On Orchard Core Add helper and block Liquid tags to the Readme The documentation has been updated about how to use the helper and the block Liquid tags. Update asset cache to check Azure Media Storage is enabled Now you will get a warning message if you don't have the correct settings for the cache of Azure Media Storage. It means an updated media cache controller to check if the Azure Media Store is enabled or configured correctly, and shows an error, rather than an exception. Etch.OrchardCore.SEO module This is a module for Orchard Core that provides useful features for SEO. For example: Hostname redirects: define main hostname to redirect all domain variations and force SSL. Redirects: create redirect content items that'll redirect a relative URL to another URL. Robots.txt: manage contents of /robots.txt. If you are building a website and you would like to do the SEO to optimize your website for success, don't hesitate and get this module from NuGet! And if you are in GitHub, don't forget to check out the other modules from Etch, they created several features for Orchard Core. For instance the Etch.OrchardCore.Fields module with a collection of useful content fields and many more! Add WithPosition extension to set Field position There is a new WithPosition extension method on ContentPartFieldDefinitionBuilder, that you can now use instead of needing to use the MergeSettings. You can find this method in the ContentPartFieldSettingsExtensions static class. Document Azure Blob Storage We have updated the documentation about how to configure the Azure Media Storage feature and how to use the Media Cache feature. Demos Flow improvements Let's set up a new site using the Blog recipe. The Page content type here has the FlowPart attached, so let's create a new page. Let's add three new paragraphs to this page with some content. After that set the percentage of every widget to 33%. You can see a different UI at the bottom of every widget. Check out the dropdowns instead of radio buttons when setting the alignment or the percentage of the given widget. When setting the percentage, the editor is now updating with the new value, and in the case of 33%, you will see the three paragraphs next to each other in one row. You can also drag and drop the widgets to easily change the position of them! Now let's add a Container, that is just a container of other widgets. You can also define the width and the alignment of the container too. But here comes the trick! Before that, you cannot move elements outside or inside a container. If you would like to move a widget inside a container, you had to create that widget again in that container, which could be quite frustrating if you decide to move a dozen widgets to a container. Now with a simple drag and drop, you should able to take any widget and put it inside a container! Do you know editors from your company who'd love this feature? Show them these gifs! Sitemaps A sitemap is a file where you provide information about the pages, videos, and other files on your site, and the relationships between them. Search engines like Google read this file to more intelligently crawl your site. A sitemap tells the crawler which files you think are important in your site, and also provides valuable information about these files: for example, for pages, when the page was last updated, how often the page is changed, and any alternate language versions of a page. Let's see how it works in Orchard Core! Set up a new site using the Blog recipe. After go to the admin page and navigate to Configuration -> Features. Here search for the Sitemaps feature and enable it. This module will add a new option under Configuration, called Sitemaps. Here you can add a new Sitemap set by clicking on the Add Sitemap Set button. Give it a likable name and then hit the Edit Nodes button. Here you can choose between two different types of sitemap nodes: Sitemap Content Types: adds a sitemap entry for each one of the selected content types. Sitemap Index Node: adds a sitemap index that acts as a container for other sitemaps. Let's create a Sitemap Content Types node to have a sitemap that contains the Article Content Types of our site! As you can see on the screen we should add a description for the sitemap node first, then the path of our sitemap. And here comes a huge table that contains every available content types of your site. Put a tick near the Article and leave the other settings as-is. Note that when you uncheck the Include all checkbox, you can adjust the number of content items in the sitemap by setting the skip and take values. For now, just put a tick here. Now if you create this node, you will have a green View button next to it. This will show the content of your sitemap. In the URL you can see that path we have set up earlier and the relevant fields of the Article content types. As you can see we previously created one additional article with the my-second-article alias. The module has a great Readme.md file where you can read a lot more about the feature and the different node types. This feature is still under development and can be found in this branch. Big thanks to Dean Marcussen for this great contribution! On Lombiq Orchard Dojo Newsletter Now we have 96 subscribers of the Lombiq's Orchard Dojo Newsletter! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

This week in Orchard - 09/13/2019

Lots of PRs merged to Orchard Core this week again coming with new fixes, and features. You could also read about the new way how you could use the localization packages in Orchard Core soon. Check out our current post for more! On Orchard Core Editor direction should respect the Localization Part culture Everything that is editable (like TextField, TitlePart, etc.) will now be configured whatever the content item's culture is. There is a new helper method, called GetContentCultureAsync that gets the CultureAspect of a content item, that will provide the CultureInfo of the content item. If you have the Localization module enabled, it will set it using the LocalizationPart of the content item (otherwise it will use the default culture of the site). Add Properties Dictionary to IShape interface We decided to provide a Properties bag on the IShape interface where you can put anything on a shape. You can do it in Orchard 1.x and in Orchard Core too, but only if the shape is a dynamic object. The readme file is updated about how can you do that using Liquid. Clean double encoding Use the tag helper instead of the ActionLink when working with localized strings. Every time when you have an ActionLink with a localized string it will be double encoded because the ActionLink only accepts a string. OrchardCore.Translations Repository In this repository, you can see a Localization folder that contains the localization for each culture for each module. Crowdin sends pull request to this repository whenever is a new translation is available. It creates new commits with every change and then AppVeyor will build the changes and this will build NuGet packages for every language. Each NuGet package will only contain the localization files for the given language. We publish the NuGet packages to MyGet prefixed with beta3. Once the dev will be merged to master it will move to nuget.org. There is also a meta-package called OrchardCore.Translations.All, that contains all the other languages. If you just point this package, you can translate your admin in any language automatically. Of course, you need to add the given language as a supported one. .NET Conf 2019 There will be the .NET Conf soon, which is a 3-day virtual developer event co-organized by the .NET community and Microsoft. Sébastien submitted a talk about Orchard Core modularity and multitenancy and he is able to speak! At September 24 at 00:00 (UTC) he will be speaking about building modular, multi-tenant ASP.NET Core apps with Orchard Core framework. Don't forget to join! Starting a new project with Orchard Core Garry Woodfine, an experienced full-stack developer has just started to work with Orchard Core. In this blog post, he writes about how you can build new Web Applications with Orchard Core, install Orchard CLI and start your CMS Website. On Lombiq Orchard Dojo Newsletter Now we have 90 subscribers of the Lombiq's Orchard Dojo Newsletter! We have started this newsletter to inform the community around Orchard with the latest news about the platform. By subscribing to this newsletter, you will get an e-mail whenever a new post published to Orchard Dojo, including This week in Orchard of course. Do you know of other Orchard enthusiasts who you think would like to read our weekly articles? Tell them to subscribe here! If you are interested in more news around Orchard and the details of the topics above, don't forget to check out the recording of this week's Orchard meeting!

This week in Orchard - 09/06/2019

Lots of PRs merged to Orchard Core this week that adds new improvements, fixes, and features. You could also read a demo about the Content Fields Indexing, that is a very useful feature for the developers: they can now query content items based on the value of the fields! Oh, and we will have a meetup soon in Budapest, where Lombiq will giving a talk on Orchard. Get ready for a longer post about these amazing features! We promise: you won't regret reading it! On Orchard Core Add ORCHARD_APP_DATA Environment Variable section If you want to change where the App_Data folder is, you can define an environment variable called ORCHARD_APP_DATA. Paths can be relative to the application path (./App_Data), absolute (/path/from/root), or fully qualified (D:\Path\To\App_Data). If the folder does not exist the application will attempt to create it. Localization files publishing When we deploy the app it will also publish the Localization folder, which is where the localization files go. Instead of the App_Data/Localization, they go into the Localization folder of the content root. Content Culture Picker improvements There is a new Liquid helper called switch_culture_url, that is responsible to return the URL of the Action that switches cultures. The ContentCulturePickerContainer is the template of the culture picker, that you can add in your front end themes to display a customized drop-down or a list of options to change the culture of the website. There was no example about how to override this using Liquid, now the documentation has an example using the new switch_culture_url helper. Workflows Internationalization Now every Task and Event have a LocalizedString property called DisplayText. With this change, you can localize the title of every activity. Make setting the page title format accessible to site administrators When you navigate to the general settings page you can find a new option called Page title format. Here you can now provide a Liquid expression to customize the way how you would like to render the title of your page. In the screen, you can see that we set the Page title format to {% page_title Site.SiteName, position: "before", separator: " -.-.-.- " %} By providing before as the position, we will show the name of the site first, then the title of the page with a custom separator. Check the second tab in the screenshot above to see the result of the expression. Handle UnauthorizedResult When trying to access an unauthorized ContentItem in the front end, the ItemController returns an UnauthorizedResult. Until there, it's correct. However, UnauthorizedResult is treated like any other error and an error message is returned: "An error occurred while executing this request." leaving us thinking there is a bug. The solution is we need to return the Forbid or Challange results, not just Unauthorized. If you are authenticated, we can just return Forbid to say you don't have access to this page. If you are not authenticated, we return a challenge, that will be redirecting you to the login page to give you a chance to authenticate yourself. In the future in most of the controllers, we should use this logic. Add documentation to health check The HealthChecks module is just enabling the middleware and the new documentation now mentions that the default endpoint is 'health/live'. Add support for typed shape tag helper properties There is a shape tag helper with the following syntax: <shape type="Foo" /> This will render the shape typed Foo. The Razor syntax to do the same is: @await DisplayAsync(await New.Foo()); You can pass parameters inside your page: @await DisplayAsync(await New.Foo(Age: 18, Color: "Green")); You can do the same using the shape tag helper: <shape type="Foo" age="18" color="Green" /> Let's say you create a file Foo.cshtm, that is the default template for the Foo shape. Inside that you can do the following: @Model.Age. What happens here is that you don't have IntelliSense for Age, because it's not typed. When you write the following in your template, what you get for the @age is the string 18. @{ var age = 18;}<shape type="Foo" age="@age" color="Green" /> In Razor, if the property doesn't exist on the type (which is the case here, because it's dynamic) it will be assigned as a string. It will evaluate that doing a .ToHtmlString(). If you really want to get integers, you have a new option in Razor tag helpers to bind a custom property with a prefix. <shape type="Foo" prop-age="@age" prop-color="Green" /> Using the prop- prefix the value will be converted to a property on the shape with the type of the variable that is passed. The @age will be the variable itself, in this case, it will keep the type of that we passed here directly to the property age, which is assigned to the shape. So the shape will keep the properties with the variable type instead of converting them to IHtmlContent. With this new improvement, you can pass complex objects to your shape types. For example, you can pass your object directly to a shape without needing a ViewModel. Demos Content fields indexing Now we have a new module which is Content Fields Indexing (SQL), that adds database indexing for content fields. You can also find documentation about the available tables for the database indexing and the usage of these index tables from a class, from a Razor template and from Liquid too. First, enable the Content Fields Indexing (SQL) module from the admin. If you are using the Blog recipe, you will have a Blog Post content type, thas has a Subtitle Text Field. Let's create some new Blog Posts. Let's create two published and one draft posts. Now head to the database, where you will see the new tables, like DateFieldIndex, BooleanFieldIndex, TextFieldIndex, etc. Because the Subtitle is a Text Field, let's check the content of that table. You can see the three blog posts here, where you can also notice that one of them hasn't published yet. If you enable the SQL Queries module, you can add a new SQL query to list the Blog Posts from the TextFieldIndex table. Hit Save and then Run the query. At the bottom of the screen, you will get the result of the query: the three BlogPost content types. Do you know developers from your company who'd love this feature? Show them that now they can query content items based on the value of the content fields! On Lombiq Talentera.Net meetup This one is for our friends in Budapest: we've partnered with the agile carrier building agency Talentera to bring you .Net meetups! The first one will be in three weeks, us giving a talk on Orchard. Join if you're in the city! Orchard Dojo Newsletter Now we have 91 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!