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 >

Orchard Harvest 2023, User Notifications - This week in Orchard (28/10/2022)

Adding default form templates for the Default Theme, adding wrapper element for all content fields, demo about the User Notifications module and don't forget to fill out a survey about the next Orchard Harvest conference! Orchard Core updates Adding default form templates for the Default Theme Currently, all of the form widgets are rendered using Widget.cshtml which renders too much HTML without any added value. The goal here is to create default Widget-Form, Widget-Input, Widget-Label, Widget-Select, Widget-TextArea, Widget-Validation, and Widget-ValidationSummary templates. It means that now, you will find these default form templates if you open up the Default Theme. Adding a wrapper element for all content fields There is no easy way to hide/show content fields "label and input as a group" using JavaScript event because there is no wrapper element to select. The goal here is to add a wrapper element to all of the content fields to allow the user to easily hide/show the entire field block using JavaScript. Here you can see the editor of the Text Field where the wrapper has now new classes with ones that you can easily use to distinguish the same kinds of Text Fields from each other. For example, the Text Field called Subtitle of the built-in Blog Post content type has the following HTML structure. Here you can see that the third class and the ID contain the technical name of the Text Field, which makes targeting the given field easier. Adding GetPageSize method to account for MaxPageSize throughout the code Now we have a new GetPageSize method in the PagerOptions class that returns the maximum number of the allowed page size based on the values of the default and maximum page size numbers. And we are using the value coming from this method for every occurrence, where we are constructing the Pager by passing it as the second parameter. Which is the default page size in this case. Demos User Notifications The goal of the User Notifications module is to push notifications to the user, meaning notify the user somehow. There are many ways you can notify a user, one of them being a web notification, you can do SMS, you can do push to a mobile application, etc. In Orchard Core right now, there is no way to send notifications, but there is a way to send emails. Let's navigate to Configuration -> Features and enable the Notifications module. This will provide a way to notify users. After you enable this module, you will see a new bell icon near the Dark mode icon at the top right. If you click on that icon, you will see a list that shows you all of the notifications that you have right now. You can click on them to mark them as read, or you can click on All Notifications at the bottom, which will redirect you to the page where you can see all of your notifications. Here you can see a list of all of the notifications available. You can use the search here, and filter them only to see the read or the unread notifications. You can sort by recently created, or by previously created. You can also mark the unread notifications as read, mark the read notifications as unread or you can delete the notifications as well. You can also hit the Mark All As Read button to mark everything as read. Now let's see how you can generate notifications! Notifications can be generated via code by injecting INotificationManager. But you can also generate notifications via Workflows. Here you can see we have a workflow called Notify Content Owner, which contains the custom activities provided by the Notifications module. Here we put two events, one for when the Blog Post content item is published and one for when the Article is deleted. And here, you can also see the two new Notify content's owner activities as well. Let's check out the content of the first Notify content's owner activity! Here you can see we have proper Liquid support to customize the summary, and the body of our notification. If we open up the editor of the second Notify content's owner activity, you can see here we have some HTML code in the body as well. To be able to render the HTML properly, don't forget to put a tick in the "The body contains HTML" checkbox. And that's not everything! If you would like to know don't forget to check out this recording on YouTube! And if you want to try out this feature for yourself, you can find the code in this PR! News from the community Orchard Harvest 2023 For those who are too young to remember, we had Orchard conferences, called Orchard Harvest. And the conference website was available under orchardharvest.org, but unfortunately, it's not anymore. The last one was in 2017 in New York. So, having another get-together is very much overdue. If you would like to see or get a feeling of how this looked like before, we have a couple of mood videos on the Orchard YouTube channel, like this one from the first conference. The point is that we should really think about organizing the next one, and we at Lombiq can take part in that or provide an organizing role with anybody who wants to take part. If you have any feedback or are you looking forward to having a Harvest again, please share your opinion with us by filling out this survey about the upcoming Orchard Harvest! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 381 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Lucene index rebuild and reset steps, Lombiq GitHub Actions - This week in Orchard (21/10/2022)

Lucene index rebuild and reset steps, update all action bars, utilize ContentTypeExtensions, and a demo about the Lombiq GitHub Actions project! Do we need to tell more about the content of our current post? Let's jump into the recent news of Orchard Core! Orchard Core updates Lucene index rebuild and reset steps Currently, when we are creating a search index from a recipe it doesn't build the index. This causes issues with Lucene and Elasticsearch where the Queries won't return any results, and also Elasticsearch will log an issue about "all shards failed" if nothing has been indexed yet in its indexes. It would be nice to be able to trigger an index to be rebuilt or reset from a scheduled background task as a one-time-only task. And from now on, you will find two new recipe steps that will help you with that: The Reset Lucene Search Index Step resets a Lucene index. The Rebuild Lucene Search Index Step rebuilds a Lucene index. You can find more information about how you can use these new recipe steps in the Orchard Core documentation. Update all action bars We have some improvements regarding the action bars on the admin UI of Orchard Core. As you can see on the screen below, there was a lot of wasted space between the search box and the New button. There was an extra round space between the filter icon and the search box and we also had uneven spaces, as you can see. The other thing is when using a mobile phone to manage contents (or any view with an action bar), the search input on the top shows up very small because of the wasted space between the search box and the New button. And here you can see the updated action bar. You can see that all of the mentioned issues are resolved like the search box is now longer, and we have equal spaces. Utilize ContentTypeExtensions We have had a static class called ContentTypeExtensions for a while now in the source, which contains several useful extensions. Like shortcuts to tell that the given content type is creatable, versionable, has stereotypes, and so on. Here the goal was to use the newly added extensions ContentTypeExtensions across the solution. Demos Lombiq GitHub Actions The Lombiq GitHub Actions project contains extensions that make a lot of things very easy in an Orchard Core or an Orchard Core-based project. If you don't know GitHub Actions or aren't entirely clear with the terminology, GitHub actions are GitHub's automation platform or CI/CD platform. Orchard Core of course also uses it to run various builds. And how you define a pipeline there is by creating workflows and/or composite actions. Workflows are what actually run, and actions are something that you can add on your own as well, these are things that workflows can call. Workflow is kind of like a program, and action is like a library that your program calls into. And of course, actions can be third-party as well. The point here is that you can use GitHub actions to automate a lot of things, like .NET builds, running tests, and doing various verifications on a pull request, and you can also do all kinds of modularization between these builds. And what we have under this project are workflows and actions. Workflows that you can call from your own workflows. Pretty much like one-liners, for example, to run the .NET build and execute a test. Actions are the building blocks that you can also use if you just want to have something specific. And we have quite a lot of actions and workflows here. Let's check out the workflow called Build and Test Orchard Core solution workflow! Here you can see how you use it. The example above is not even a minimal usage actually, it can be even shorter. This can be your GitHub Actions workflow in your own repository with an Orchard Core application, where you execute the workflow that we provide here. This is actually used in Orchard Core Commerce as well. If you check out the build-and-test.yml file inside the repository, you will find all the code that is necessary to run such builds. If you check out the details of a pull request inside the Commerce repository, you will see there are builds for Ubuntu and Windows as well. These are all the automated checks that we run. This is quite a long build because it's not just a .NET build, it also runs all kinds of static code analysis. It verifies that .NET packages are consolidated, and it also runs unit and UI tests with SQL Server and Azure Storage actually. And the Lombiq GitHub Actions projects contain a lot more than that! Are you interested in the details of what you can achieve if you use this project in yours too? If your answer is yes, or you want to know more about this automation platform check out this recording on YouTube for more! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 365 subscribers! We have started this newsletter to inform the community around Orchard of 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!

New AddDataMigration extension, show the container's header for List Part - This week in Orchard (13/10/2022)

Add notes in the documents on how to configure YesSql, and show Bag Part content when the post request generates errors in the Bag Part. New AddDataMigration extension method, demo about showing the container's header for List Part, and many more are waiting for you in our current post! Orchard Core updates Add notes in the documents on how to configure YesSql We have a page in the Orchard Core documentation that describes how you can run SQL queries by creating a DbConnection instance and obtaining a custom ISqlDialect from IStore from the YesSql namespace in the YesSql.Abstractions package. Or how you can handle prefixed tables. Now this page has been updated with a new section that describes how you can configure YesSql by configuring YesSqlOptions. Show Bag Part content when the post request generates errors in the Bag Part Assume we have a content type (ex., Product) with a Bag Part attached. The user creates new or edits existing products and provides invalid data for items within the Bag Part. The post request fails validation which is great! However, the Bag Part will be rendered in a collapsed state. So, the user is left wondering where the error is until the user uncollapses the Bag Part and sees the highlighted error. The solution here is when rendering the Bag Part, we should uncollapse the Bag Part if there is an error in any of its contents. We can try this one out easily. Let's say we have a site set up with the Agency recipe (that recipe contains the Landing Page content type which has several Bag Parts attached) and edit the content definition of the Service content type. Here we edit the Icon Class Text Field and make it required. Now it's time to edit the predefined Landing Page content item and remove the value of the Icon Class from one of the attached Services. And as you can see here, the Service content type is uncollapsed, making it easier to identify where the error comes from. New AddDataMigration extension The goal of the new AddDataMigration extension is to shorten code like services.AddScoped<IDataMigration, CustomMigrations>(); to services.AddDataMigration<CustomMigrations>();. And if you open up a given Startup.cs file (in our case the one that sits in the AdminDashboard module), you will see the usage of this new extension. Demos Show the container's header for List Part There is a need to extend the look of the default List Part. This would mean that the buttons that allow you to edit the container content item itself and to add contained content items now will be placed in a new line on the top to make the search text box wider. These navigation buttons now appear on every page where List Part or Contained Part are used for easier navigation. Here you can see the updated page of the predefined Blog content item. And if you would like to edit the given Blog content item or create a new Blog Post, you will see these new buttons there as well on the top. But now let's edit the content definition of the Blog content type and hit edit near the attached List Part to edit the List Part itself. Here you can find a new checkbox with a hint "Check this option to show a header for the owning content." Let's put a tick in this checkbox and see what will happen when we navigate back to the list item's view. As you can see, now we have a new line here that shows the header for the owning content, meaning the header of the Blog content item, which just shows "Blog" in this case. This new line is also available on the page where you edit the blog content item itself and on the page where you create a new blog post. But let's do some tricks now! Let's say that we edit the definition of the Blog content type and add a new Media Field to it, called Logo. After we can edit our predefined blog content item and upload an image using our new Media Field. The header is simple by default, but we can override it easily using shapes! Let's say that we want to display that logo in this new line! To do that, we needed to create a new shape template called Content-Blog.Header.cshtml (we are using Razor and the technical name of this content type is Blog). Here you can see that this row contains two columns, and we would like to display the image that is selected by our Media Field called Logo in the first column. And now, the only thing to do is to navigate back to the admin UI of Orchard Core and check out the brand-new look of our Blog! If you want to try this out right now, you will find the code in this pull request. And as always, if you want to see a recording about this feature, this will be your video on YouTube! News from the community Orchard Core Commerce is now available on all DotNest sites Orchard Core Commerce is now available on all DotNest sites! A few weeks ago, we mentioned the current state of the Orchard Core Commerce module and one of the hugest improvements of adding Stripe Payment to the solution. And now you can start building your e-commerce site on DotNest! Check out our announcement for details here. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 355 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Smithsonian Folkways Recordings now upgraded to Orchard Core - This week in Orchard (06/10/2022)

Provide IConfiguration extensions to configure certain modules, replace StatusCode() when possible, demo about migrating Smithsonian Folkways Recordings to Orchard Core, and many more are waiting for you in our current post! Orchard Core updates GraphQL 4 Now Orchard Core uses GraphQL 4 instead of 2.4.0. The next step would be to update to GraphQL to 7.1.1, which is the latest release currently. Provide IConfiguration extensions to configure certain modules Several modules expose their configuration via IOptions<T> but only include site settings IConfigureOptions<T> for it: Email, Facebook, GitHub, Google, and Reverse Proxy Configuration. These could also provide extension methods like OrchardCore.Shells.Azure does with AddAzureShellsConfiguration() so the configuration can be easily provided by e.g., the appsettings.json file. And now we have these extension methods. If you check out the ConfigureEmailSettings extension method, you can see a sample for that which reads the settings from the appsettings.json file. This means the OrchardCore.Email module allows the user to use configuration values to override the settings configured from the admin area by calling the ConfigureEmailSettings extension method on OrchardCoreBuilder when initializing the app. Replace StatusCode() when possible We have some helper methods that can be used instead of returning StatusCode(). And there is also a new extension method called InternalServerError that produces an InternalServerError response. Demos Smithsonian Folkways Recordings Orchard Core migration For those who are unfamiliar with the Smithsonian Folkways Recordings site, the primary purpose is to showcase music and its cultural impact, as well as to provide related educational content. The news from the world of music is also available in the form of articles, and users can digitally purchase albums and other content as well. Additionally, users can also request licenses to use music for their purposes. The site was recently migrated from Orchard 1.x to Orchard Core and its process includes recreating and reimplementing everything present in the previous application as well as adding some important new features like UI tests. The home page serves navigation purposes for the most part. It shows the latest available content on the site, including new releases, artists, vinyl reissues, news, etc. You can also browse the site by filtering by genre, location, artists, or record labels. Users can use the License request form to request licensed music for their personal uses. You can navigate between the editor groups using the top navigation bar or you can also use the Back and Continue buttons. The data that the user enters is always saved when you click the Continue button, which is by design. There is a song search feature too that can be used to find the song which they would like to license. The registered users of the site can use the LDAP server and NetSuite login options as well for authentication so they don't necessarily need an Orchard Core user account to log in. One of the largest parts of the migration process is data migration which was handled by Jean-Thierry Kéchichian. If you are interested in how he did that or some other technical details, check out this recording on YouTube for more! News from the community Smithsonian Folkways Recordings now upgraded to Orchard Core As you can read, the Smithsonian Folkways Recordings now upgraded to Orchard Core, migrated from Orchard 1.x, and we worked a lot on it too! Here you can check out the case study about the migration process. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 356 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Extend user permissions, add Contained Stereotypes Bag Part Settings - This week in Orchard (30/09/2022)

Add Contained Stereotypes Bag Part Settings to allow a user to include content types by stereotype, add Displayed Stereotypes property to Content Picker Field Settings, demo about extending the user permissions, and many more waiting for you in our current post! Orchard Core updates Add Contained Stereotypes Bag Part Settings to allow a user to include content types by stereotype When attaching Bag Part to a content type, the user must explicitly set Contained Content Types with an array of content types to be included in the Bag Part. This is good for most cases; however, it would be great to allow for setting the contained content types using Stereotype. The stereotype would be in addition to not in place of Contained Content Types. For example, we want to group all Contact Methods (phone number, address, email address, etc.) by a stereotype type called ContactMethod. All of these content types share a similar functionality which is a way to contact a person. Now we created a Person content type and attached a Bag Part to it. In this case, we had to explicitly specify each content type in the Contained Content Types. But if a new content type was added later from other feature/module, the user would have manually to edit the Bag Part settings every time/everywhere ContactMethods are used to add the new content type which isn't efficient. So now the Bag Part is more flexible. And as you can see here, now we have two radio buttons under the Contained Content Types option where the user can select Content Types or Stereotype. Add Displayed Stereotypes property to Content Picker Field Settings And this one is quite the same as the previous feature but for the Content Picker Field. For example, we want to group all to-do items (appointments, meetings) by a stereotype type called ToDoTask. All of these content types share similar functionality which is a to-do task. Now we want to use Content Picker Field in a different content type to allow the user to select a to-do-task of any kind. In this case, we have to explicitly specify each content type in the DisplayedContentTypes. But if a new content type was added later from another feature/module, the user would have to manually edit the Content Picker Field settings all time. Everywhere to-do tasks are used to add the new content type which isn't efficient. So, let's say we navigate to the editor of a Content Picker Field. And here you can say that you can select the Contained Content Types to: Display All Content Types Content Types Stereotype Add settings to form widgets There was a bug in OC. The option editor wasn't loaded when trying to add Select Input while creating a form. Also, the edit button did not open the modal that would allow you to populate the options using JSON. If the content is saved, and the page is loaded again then the modal and the options editor work just fine. Another form-related improvement is validation. When creating a form using the Form input widgets like (Input, Select, and Text Area) there is no easy way to add a label and validation elements to the input. The current approach is to add a label widget and then a validation widget which is not always ideal. We can make this process much simpler by adding settings to the Input, Select, and Text Area widgets with the following properties: LabelOption an enum value with the following values (None, Standard, ScreenReaders). By default, None is selected to keep it backward compatible. ValidationOptions an enum value with the following values (None, Standard). By default, None is selected to keep it backward compatible. Now, if the user selects an option other than None in the settings, we’ll create the label in the same widget block. The same applies to ValidationOptions. This will make things like dragging/dropping widgets during edit and controlling the size much easier. At the same time, we output less HTML code. And if we add the validation rules, we’ll have more validation logic which makes the widgets more useful. And now, the editor of the Select Input looks like the following with the additional options. And of course, the same applies to all of the built-in form inputs. Demos Extend user permissions A couple of months back there was a need reported to have some roles to be able to edit a user and some not. And there is a conclusion that the user interface is not very flexible at the moment with the permissions. So, it kind of makes it hard if you have a unique case where you need some specific users to be able to do stuff. And also, to set up who can see what users, when you are listing the users. To be able to test out this feature with us, you have to check out this PR on GitHub. The first thing that you will notice is the new permissions regarding Users. In this case, we navigated to Security -> Roles and edited the Moderator role. There are new permissions, for example, Assign any role, Delete any user or Delete users in role - Administrator, List all users, etc. So, you can say you can list all the users, but it doesn't mean you will be able to edit all the users. If you try to edit a given user, you will notice something new here. As you can see, the user name of the user is not editable, but you can edit the email address of the given user. This is controlled by settings that you can reach under Configuration -> Settings -> User Profile Settings. As you can see, here you can allow or deny changing the user names or email addresses of the users. But now back to the users' list. Let's say we have some predefined users and made some changes regarding the permissions of the Moderator role. Now, we logged in with a user who has the Moderator role. After that, the user with the Moderator role will see something like this. First of all, you can notice that there is a little badge under every user that shows the roles the user has. You can also see that this user has permission to see users in the Editor role, but they can't edit or delete the editor user. Now let's edit the author user! Here you can see that this user can edit the settings of this user but can't fully manage the roles of the author user. They have the option to add or remove the Author role but that's it, nothing more. And we are just showing you some simple scenarios about what you can achieve and how you can customize the user permissions. If you want to see more complex scenarios, head to YouTube for a recording! News from the community Helping Global Health build an Advanced Form Builder using Form.io When Global Health from Australia approached us with the request to build an advanced form builder using Form.io, it promised to be an interesting project. They were looking to integrate this new form builder deeply into MasterCare+, their Multi-Tenanted SaaS-based platform for Health Care which is built on Orchard CMS. It would allow creating custom forms for a wide range of scenarios in the health care domain, using the advanced editing capabilities of Form.io. The solution built by Lombiq was an important step in bridging the gap between paper forms and electronic health care management. Check out the full post here! Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 354 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Archive Later Feature, Notifications Feature - This week in Orchard (23/09/2022)

Archive Later Feature, extract GetLanguageDirection() and IsRightToLeft() to CultureInfoExtensions, introduce EnabledByDependencyOnly flag for features to allow the feature's state to be auto, and a demo about a feature called Notifications! Check out our post for the details! Orchard Core updates Archive Later Feature Back in 2020, we mentioned the Publish Later Feature which adds the ability to schedule content items to be published at a given future date and time. Now here comes the Archive Later Feature, which provides a way to unpublish content items at a given time. Let's see a simple example of the usage! Open up the admin UI of Orchard Core and head to Configuration -> Features and enable the Archive Later module. If you would like to use this feature with your content type you have to edit its definition by attaching the Archive Later Part to it. Let's attach the Archive Later Part to the Blog Post content type! Now let's edit our predefined blog post! At the bottom of the editor, you will see a new input Tag Helper with the datetime-local input type. If you set the date and the time here and hit the Archive Later button, the status of the current version will automatically change to draft when the time goes by using a background task. We also have a Cancel Archive Later button, so we can cancel the archiving process. And in the SummaryAdmin list, you also had a little message that shows you the date and time when the content item will be archived. Extract GetLanguageDirection() and IsRightToLeft() to CultureInfoExtensions We have some extension methods for CultureInfo to deal with language direction. These extension methods were placed in the LanguageDirection class and now they have their own class called CultureInfoExtensions. So, from now on you can find these extensions here. Small change but nice to have extension methods in a separate class. Introduce EnabledByDependencyOnly flag for features to allow the feature's state to be auto To represent this new change, we will use the features that you can check out in detail in the demo down below regarding the Notifications Feature. So, let's say you are on the Features page and search for the "notifications" word. Here you can find the Notifications module, which is only enabled if you enable one of its dependencies. So, you can't enable it right away. But the Email Notifications module requires it, meaning if you enable the Email Notifications module, the Notifications module will be enabled as well. And if you disable the Email Notification module, the Notifications module will be disabled as well because none of its dependencies are enabled. And it's a flag that is very easy to use! If you open up the Manifest.cs file of the OrchardCore.Notifications module (can be found in this branch), you will see the feature with ID OrchardCore.Nofitications has this property set to true. It means that if we enable one of the dependencies of this feature, this module will be automatically enabled. And if none of the dependencies of this feature are enabled, then this module will be automatically disabled. Demos Notifications Feature The Notifications Feature provides a way to be able to send notifications to notify users. You could implement a push notification to a mobile phone, you could implement a web notification, you can have an email notification, etc. For right now you can see the implementation of the email notification, and the Email Notifications module is the one that provides you with this feature. Let's enable it! After that, we can edit one of the existing users on the site and say that we want to send email notifications to this user. And if you implement a push notification or a web notification, then you will see a flag for those as well and we can set up what kind of notifications we want to send to the given user. But this might feel incomplete without the Notification Templates feature which provides a way to create notification templates. Let's enable this one as well! And this will mean that now we can create new Notification Template content items. Let's create a new one and call it "Welcome email for new users template". We will send this email any time a new user is created. Here you can select the provider that you want to utilize, let's select the New user notification here. And as you can see, you have a subject and a body. There are also username, password, and email arguments, that we automatically create because this provider is aware of them. It means you can inject these into the subject and the body of the email that you want to send. The idea here is if you create a new user as an admin you might want to send their temporary password in an email. Here you can use Shortcodes and Liquid templates as you can see. So, we mentioned that we have a New user notification provider. If you enable the third notifications-related feature, called Notification Templates for Contents, it will give you more providers to use. So, if we create another Notification Template, now we can select the Content based notification provider too. It provides you with more templates (DisplayText, ContentItemId, ContentType, etc.) because it has more awareness. At the bottom, you can control who should be the person who receives this. But here right now you don't have the way to select that I want to send out this notification when someone publishes the Article content type. So, selecting the content type and the event is not here. To do that, you have to edit the content definition of a given content type. If we select the Blog Post one, for example, you can see a new setting, called Notifications. If you select to send a notification, you can define which event you want to use and the given notification template. This feature is a PoC and if you want to check out the implementation or try it out in your solution, you can find the code in this branch. And if you prefer videos, check out this recording on YouTube to see more about this feature! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 350 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Add fallback alternate when a custom stereotype is used, tenant removing - This week in Orchard (16/09/2022)

Add fallback alternate when a custom stereotype is used, validate database connection before allowing a tenant to be added or set up, remove localization workaround in Data Annotation Attributes, and a demo about the upcoming tenant removing feature! Check out our post for the details! Orchard Core updates Add fallback alternate when a custom stereotype is used The idea here is that when you create a stereotype, before this change, you had to create templates for this stereotype if you intended to display or edit items of this stereotype. And now, there is a fallback shape for stereotypes such that if you don't create custom templates, it will use a standard, default template that is valid for any stereotype. How it works is just to let's use the Content shapes for anything when we don't have a custom template. It prevents showing error messages when you create a stereotype and try to create a content item from this stereotype. And you can test this one easily. Just navigate to the admin UI of Orchard Core and head to Content -> Content Definition -> Content Types, where you can find the Create new type button to define your new content type. Add a name to it and hit Create. We will not add any Parts to it right now. Set the Stereotype to Cat and hit Save. Now we can create a new Animal content item by clicking on the New button and selecting Animal under Content -> Content Items. And as you can see, Orchard Core now renders the default Content_Edit template as a fallback instead of throwing an exception. Validate database connection before allowing a tenant to be added or setup When adding a new tenant, we allow the user to set a prefix to the tables to enable reusing the same database for multiple tenets. However, we don't validate that the prefix isn't already used first. The problem with this is that it throws an exception. Let's say we have a tenant with a URL prefix test and we selected the SQLite database. Now let's create another tenant using the same URL Prefix and database preset. As you can see, now we have a validation error. But we also have validation for connection strings as well. Let's say we would like to use SQL Server and provide a connection string that is invalid. In this case, you will face an error like "The provided connection string is invalid or server is unreachable". Remove localization workaround in Data Annotation Attributes Two years ago, when Hisham Bin Ateya started the support data annotations PO localization PR, there was a long discussion to support localization in data annotations. Back in the day, Antoine Griffard did a workaround to achieve the goal by using IValidatableObject, and now it's time to remove this workaround and use the new way of doing this. This means we can remove the need of implementing the IValidatableObject from several ViewModel. And from now, on you can use some attributes which help you print localized error messages. And now there is an attribute for email validation and URL validation as well. Let's see an example quickly! As you can see here, the RegisterViewModel implemented the IValidatableObject to be able to validate the properties inside the class. Now, instead of using the IValidatableObject, we can add attributes to these properties, and here comes the new EmailAddress attribute as well. As you can see from the screen, the new implementation of the ValidationAttribute can be used to validate your model by returning a localizable error message. Demos Tenant Removing The option to be able to remove tenants is a long-requested feature, and for now, we are very close to shipping this feature, thanks to Jean-Thierry Kéchichian. Let's see how it will work! For this demo, we will navigate to GitHub and checkout this branch. Now, let's add some tenants to be able to try out this feature. As you can see, we have added 3 tenants. The Agency and the Blog ones are tenants that we have already set up, but the tenant called test is waiting for setup. Here you can see that we have the Sites folder under App_Data where each of the tenants has its own folder containing the Media files for example. And now we also have a wwwroot folder under OrchardCore.Cms.Web, which contains a folder per tenant like in the previous case. This means now each tenant can manage their own cached files under wwwroot. When we remove a tenant, the logic will also remove the folder of the tenant under the wwwroot and the Sites folders. And now it's time to delete a tenant! To be able to delete a tenant, we should disable it first, which means it will be not served, and we will be able to compose an internal ShellContext with all the features that the tenant has, even if it is installed or not. You can also remove multiple tenants by using bulk actions. And this is just the surface, there are still some things to do. If you would like to see the current state of this feature and do a deep dive under the hood, check out this recording on YouTube! This feature is sponsored by Lombiq. News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 347 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Content Relationships guide, Orchard Core Commerce Stripe Payment - This week in Orchard (09/09/2022)

It's time to publish the results of the Orchard Core Commerce survey and the topics that made it into the MVP as the short-term goals. And we have just added Stripe payment integration to the checkout process! Check out our post for the details! Orchard Core updates Content Relationships guide How can you relate (connect) content items to other content items in Orchard Core? When would you use each built-in option? This new guide aims to clear up the available options by detailing: Bag Part (BagPart) for Embedding Content Items within a Parent Item Content Picker Field for Many-to-Many Relationships of Specific Items Flow Part (FlowPart) for Building Structured, Responsive Layouts List Part for One-To-Many Hierarchical Relationships Taxonomies for Categorization and Tagging Demos Orchard Core Commerce Stripe Payment Orchard Core Commerce will be an Orchard Core port and partial rewrite of the open-source Nwazet Commerce module that was built for Orchard CMS 1.x. Nwazet Commerce was initially built in 2012 by Bertrand Le Roy, loosely based on a commerce sample by Sipke Shoorstra. The initial goal of Nwazet Commerce was to power the website of the hardware startup Nwazet. While Nwazet is no longer operating, the Nwazet Commerce project went on and was further developed by a group of passionate contributors who are using the platform for their own, and their customer's websites. Like Orchard, Nwazet Commerce was built with extensibility in mind, and as such, it has its own extensions (typical examples include local tax and shipping modules). It's also pure, idiomatic Orchard. Orchard Core represents a major evolution of the Orchard design principles and is sufficiently different that running Nwazet Commerce on it will necessitate significant work. As such, the community decided that starting from a blank slate was the best way to go, so they will port Nwazet Commerce piece by piece, being careful to accurately apply Orchard Core's new design principles. The community also decided to adopt a new name that gets rid of the now obsolete origins and establishes our ambition for the module to become the go-to commerce module for Orchard Core. And at the beginning of May, we published a demo where you could see the current state of the module. This time we will see a demo about the basic implementation of Stripe Payment integration (without taxation, shipping, etc.). Stripe is a payment service provider that business owners can use to accept dozens of payment methods, from credit cards to buy now, pay later services. Stripe Payments handles the steps between a customer providing their card information and learning that their payment has been accepted. You can try out the Orchard Core Commerce solution just by cloning the repository from GitHub, or you can download it as a NuGet package as well from NuGet.org. For this demo, we will set up our site by using the OrchardCore Commerce - Development recipe, which adds some built-in content to our site that we can use during development (and during our demo of course). After, we can head to Configuration -> Features and enable the three commerce-related modules: Orchard Core Commerce: Registers the core components used by the Commerce features. Orchard Core Commerce Session Cart Storage: Registers session-based shopping cart persistence. Orchard Core Commerce Settings Currency Selector: Currency selector that uses display currency configured in settings. Useful for Dev/Test scenarios. Now we can set up the Stripe API (Configuration -> Settings -> Stripe AP) by providing the publishable and the secret key. These keys are publicly available test keys, so feel free to use them for testing and development. The Readme.md file of the Commerce module also contains these keys. Now let's navigate to Content -> Content Items to check our predefined content items. The Product is a content type that can be added to the cart, and users can pay the price of the products. We have one, called TestProduct, let's add another one called Cheese. Here you can see we can set up the name, the SKU, and the base price of the product with the currency used as well. Let's say this Cheese will cost 4.50 USD. Now it's time to add the predefined product and the Cheese to the shopping cart! You can do that by navigating the details page of a product, and after setting up the quantity, you can click on the Add to cart button. Let's say we would like to add one Cheese and one TestProduct to our shopping cart. The shopping cart is available under the /cart URL, but the site will redirect you to this URL too, if you click on the Add to cart button. As you can see here, our cart contains two items: one TestProduct with a price of $5.00 and one Cheese with a price of $4.50, which costs $9.50. It's time to pay by clicking on the Checkout button! On the checkout page, you can set up your billing address and shipping address but let's focus on the credit card field right now, which comes from the Stripe API. You can find some credit cards in the Stripe documentation and in the Orchard Core Commerce Readme that can be used for testing different scenarios. Like handling a card that has insufficient funds or which has expired. But you can also use a card that requires 3D Secure 2 authentication. The 3D Secure standard - often known by its branded names like Visa Secure, Mastercard Identity Check, or American Express SafeKey - aims to reduce fraud and provide added security to online payments. 3D Secure 2 (3DS2) introduces "frictionless authentication" and improves the purchase experience compared to 3D Secure 1. It is the main card authentication method used to meet Strong Customer Authentication (SCA) requirements in Europe and a key mechanism for businesses to request exemptions to SCA. It means you cannot pay right away because you will see Stripe's own 3DS2 authentication panel. In live mode, you can see the bank's authentication panel here. If you click on the Complete button here, you can imitate that the purchase was successful. And in that case, the module will redirect you to a "Thank you for your purchase" page. And after a successful payment, a new Order content item will be created, which you can see on the content items list. Right now, the Order content item contains an automatically generated Order Id, a list with the charges (kind, amount, charge text, etc.), and the status of the order. The order contains the billing address and the shipping address as well. And that's not everything! If you want to know more regarding the current state of the Orchard Core Commerce module, don't hesitate to check out this recording on YouTube! News from the community Orchard Core Commerce survey results and MVP As you may know, Lombiq provides stewardship for the Orchard Core Commerce module. That actually means that we will do code reviews and work on features and fixes. To have that, we started this thread and added an Orchard Core Commerce MVC planning survey. This was about asking the community what the most essential features for you would be in an Orchard Core-based e-commerce solution. And now, we have the results and published an announcement of what will be in the MVP and the short-term vision of the project. Thanks to your feedback, we have a more straightforward impression of the community's priorities, and some new developments are already coming in. Feel free to check it out and join the discussion especially related to the bigger issues like taxation or discounts. Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 345 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Add PagerOptions, Output Caching for ASP.NET Core 6.0 - This week in Orchard (02/09/2022)

Fix the password generator to meet the password requirements, add PagerOptions, and a demo about Output Caching for ASP.NET Core 6.0! Let's get started! Orchard Core updates Fix the password generator to meet the password requirements A few weeks ago, we mentioned that you have the option to generate passwords on the user creation form. But how can you do that? Head to the admin UI of Orchard Core and navigate to Security -> Users. Here you will find the Add User button. Click on it! This will navigate you to the create user page, where you can find this feature, where you can provide a password for the newly created user, and you have the option to generate a random secure password or copy the password to the clipboard. The password generator had an issue which was password randomness occasionally omits a special character or number. Password should include a number, lower and uppercase letter, and special character. Now, this has been fixed, and the generated password meets the requirements described here. Add PagerOptions When you navigate to Configuration > Settings -> General, you have the option to set up the default page size which is the default page size of lists. But you also have the option to define the maximum number of pages that can be paged (MaxPagedCount) and the maximum page size that can be set by a user (MaxPageSize). And from now on, you can define the pager options using appsettings.json as well. Here you can see that you can easily set up the values for all three properties. Demos Output Caching for ASP.NET Core 6.0 Output caching stores the generated output of pages, controls, and HTTP responses in memory. Output caching enables you to cache different versions of content depending on the query string and on form-post parameters to a page, on browser type, or on the language of the user. And now, .NET 7 has an Output caching middleware with a sample that illustrates the usage of ASP.NET Core Output caching middleware. The application sends a Hello World! message and the current time. A different cache entry is created for each variation of the query string. If you open up the Startup.cs file of this sample, you can see how to set up Output caching. You just need to say app.UseOutputCache(); and by using the AddOutputCache, you can use some options as to what to cache and how to cache it. You can cache a given endpoint as well by just saying app.MapGet("/query", Gravatar.WriteGravatar).CacheOutput(p => p.VaryByQuery("culture"));. But it's only available in .NET 7.0 preview and not in .NET 6.0. Sébastien Ros published a custom package to NuGet that copies the code from the ASP.NET Core repository but targets 6.0. It could be done because there is nothing in this feature that requires things from .NET 7.0. And Orchard Core targets .NET 6.0., so you can have Output caching in Orchard Core! But how can you do that? Let's say you add a new module to Orchard Core and reference the Preview.OutputCaching NuGet. Now you have to modify the Startup.cs file of your module. The code is very simple, in the ConfigureServices, we call AddOutputCache, and in the Configure we say UseOutputCache. But there are lots of options to configure policies and roles. So, by default when you use AddOutputCache, it doesn't cache anything until you tell what to cache (like a route, an action, path, etc.). By calling the options.AddBasePolicy(build => { });, it will just enable the default policy on everything, which is to cache everything. But only if it's a GET request and only if the user is unauthenticated. Now let's try out this feature! Open up the homepage of your site and check the Network tab of the DevTools window when using Chrome. Here you can see a new Response Header called age, with a value of 9. The age header contains the time in seconds the object was in a proxy cache. This means this is a response from the cache, and the cached value is from 9 seconds ago. The default cache, in this case, was 1 minute, after 1 minute it got a fresh entry, and by refreshing this page you can see the increasing value of the age header. After it reaches 60, the counter will start from 0 again. Interested in how to customize Output caching or maybe you would like to help the community build a module for Orchard Core that provides Output caching? Then check out this recording on YouTube for more! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 343 subscribers! We have started this newsletter to inform the community around Orchard of 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!

Prevent Trumbowyg from converting <div> to <p> element, Elasticsearch feature - This week in Orchard (26/08/2022)

Prevent Trumbowyg from converting <div> to <p> element, reduce memory when reloading settings of a given tenant from the database, and a demo about the upcoming Elasticsearch feature! Let's get started! Orchard Core updates Prevent Trumbowyg from converting <div> to <p> element When using HtmlBodyPart or HTMLField with either WYSIWYG or Trumbowyg, the editor converts <div> elements to <p>. Also, when the user switches into code insert mode, the text area does not take up the full size of the editor. Steps to reproduce the behavior: Add HtmlBodyPart or HtmlField to a content type, and use either WYSIWYG or Trumbowyg editors. Create new or edit an existing content item. Click on <> of the editor to switch into code insert mode and insert the following. The issue is that the Semantic option is enabled by default. By enabling Semantic, it generates a better, more semantic-oriented HTML (i.e. <em> instead of <i>, <strong> instead of <b>, etc.), meaning: $('.trumbowyg').trumbowyg({ semantic: { 'b': 'strong', 'i': 'em', 's': 'del', 'strike': 'del', 'div': 'p' }}); The idea is that the "Wysiwyg" editor option should not alter the "Tryumbowyg" editor default behavior. This is why we have the "Trumbowyg" editor option that allows changing its behavior for your own needs. So, the fix was to set the semantic: false on the Wysiwyg templates and don't change anything on the Trumbowyg templates. Reduce memory when reloading settings of a given tenant from the database There appears to be a memory leak caused by the usage of IConfiguration as the backing for ShellSettings. Memory used by each ShellSettings instance is not being freed for garbage collection due to some fairly crazy gcroots even if you intentionally release the ShellSetting. Most of the memory is being used by Strings related to the DatabaseShellsSettingsSources with the VersionId field being the largest consumer of memory. The problem is that the DatabaseShellsSettingSources contains data for ALL tenants (which can be 2000+ in some cases) even if you're only loading/reloading a single tenant. So, among our tenant config/settings sources, one of them is by default the tenants.json file. In fact, when we reload a given tenant, we don't need all data from this source but only those related to this tenant. When we add this source to the config stack of a given tenant, if we still use builder.AddJsonFile() we have no choice, we can't split this file into smaller parts per tenant. But when this source comes from the database, we do a builder.AddJsonStream() on a MemoryStream that holds all data of this source, so here the idea is to only hold in memory the data related to this tenant. To do so Jean-Thierry Kéchichian added a method to the interface of this source allowing to pass a tenant name. So that when the source comes from the database, each time we reload a specified tenant we still create a MemoryStream but that only holds the data related to this tenant (not all tenants). When calling this new method on the other implementations of this source, they just ignore the provided tenant name by calling the existing method without this parameter. Demos Elasticsearch feature Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. This time we will see how you can use Elasticsearch in Orchard Core using the Elasticsearch feature, which can be found in this pull request and will be released soon. The Readme.md file of the module describes how you can use this feature for development and testing purposes by using Docker. We won't go into the details of how to install Docker and use the Docker Compose file, the Readme.md file mentioned has a nice step-by-step tutorial about that part. So, let's say we have a Docker container running the Elasticsearch image on port 9200 (the default one). The Elasticsearch module connection configuration can be set globally in the appsettings.json file or per tenant. The connection types documentation and examples can be found at this URL. To try out this feature, you need to enable the Elasticsearch feature under Configuration -> Features. You can also see a Content Picker for Elasticsearch, just like we have for Lucene, and a Worker. And of course, don't forget to enable the Search module as well, which adds front-end search capabilities. We will use this feature to try out the new Elasticsearch feature. The Elasticsearch module has some settings in the admin, where you can configure the search settings for the module (Search -> Settings -> Elasticsearch), and you can decide which fields you want to use for the search pages. It's quite the same as Lucene's settings, but it's a separate page because you can index different fields for Elasticsearch and Lucene. And for the search form, we can decide which provider we want and it will work at runtime. This means you can seamlessly switch from one indexing provider to another one. You can set this up under Search -> Settings -> Search. If you navigate to the default URL of the search form (/search) you can use this form as you would use it in the case of Lucene. But of course, you need to have an Elasticsearch index that you can use while doing a search and the indices can be set up under Search -> Indexing -> Elasticsearch Indices. As you can see, here we created a new index called default_search and indexed some content types. And now, you can use the search form to return results based on your query. The default_search index contains the Article and the Blog Post content types, so if we use the "man OR about" query, the site will return us two results, the default blog post, and the default article content items. And we are just scratching the surface here. The Readme.md file contains a lot more: how to create an Elasticsearch index during recipe execution, how to create an Elasticsearch query from a Queries recipe step, how to use Web APIs to execute a query, and a lot more! Check out this recording on YouTube if you would like to know more about this upcoming feature! News from the community Orchard Dojo Newsletter Lombiq's Orchard Dojo Newsletter has 341 subscribers! We have started this newsletter to inform the community around Orchard of 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!