3. 2. Implementing best practices
As the development starts, you need to ensure that the developers are following best practices. It can be difficult to identify what best practices to follow for a particular implementation, but we identified 7 Key Concepts for Successful Development in Kentico. Each of these concepts are applied differently depending on the particular requirements and details of the task at hand. However, the basics of these concepts can be applied broadly.
There are two sides to security. The first is related to properly configuring access to content and functionality for authorized users.
The second is making sure that hackers are not able to exploit flaws in the implementation to gain unauthorized access to content and functionality.
When it comes to Kentico, you need to consider the following:
- User permissions and access control lists (ACLs)
- Proper configuration of web parts
- Sanitization of user input to SQL injections and cross site scripting attacks
- Secure data storage/transfer
Kentico administration UI, out of box controls, and APIs make it easy for you to secure your application by providing an easy to use UI, some automatic protections, and tools to make sure you are able to easily secure your code.
Many times, developers primarily focus on just making sure what they build is functional. This can lead to scalability issues, higher running costs, or even dissatisfied users.
Kentico does a lot of optimization automatically, and provides lots of ways to get better performance out of your project with features like:
- Caching as a first class citizen:
- APIs that can be fine tuned to retrieve only the necessary data.
- Built in debugging tools allow easy access and visibility into the inner workings of the system.
It's important to note that while Kentico does a lot of things automatically, it can be very easy to introduce performance issues. Here are a few practices to keep in mind as you develop:
- Introduce as few (ideally zero) SQL queries as possible.
- Make sure that you have a caching strategy and that it is working.
- Review the performance of your custom code using the debugging tools in the administration interface.
- Review how the project is configured, as some options like analytics and online marketing features can add some overhead to requests (only enable what you need).
- Consider first page load time as well as primed cache load time.
- Consider integrating third-party tools to gain further improvements such as minifying your HTML with WebMarkupMin.
When building something new, you need to consider what it depends on (data structures, third party APIs, etc.) and what will depend on it (templates, custom modules, etc.).
It is important to plan how what you are building will interact with its dependencies in order to avoid re-work or extra effort. This is also important when considering how to deploy new features/functionality down the line.
Some examples of dependencies to think about in Kentico include:
- Page types and content needed before being able to build a template.
- Cache dependencies being configured properly.
- Code files and resource strings for a custom module class needed before developing module UI.
- Third party libraries must be available in .NET or as a web API before you can interact with them inside a Kentico project.
- Relationships between custom built features must be understood.
Whether the project will be maintained by the same team or not, implementations should be created with future maintenance in mind.
If something is built sloppily the first time, maintenance can easily be exponentially more costly. It is important to consider every aspect of what you are developing when it comes to maintainability.
For example, you will want to pay attention to some of the following things in Kentico:
- For web parts, use short control IDs with descriptive titles that identify the purpose and control ID (e.g. control Id: "MN", Title: "Main Navigation [MN]").
- Name code files appropriately (e.g. use the class name of the class contained in the file).
- Store code files in an appropriate location in sub-directories identifying it as custom for the project and based on the namespace (e.g. /CMSWebParts/MCP/ProductConfigurator.ascx(.cs), where MCP is an abbreviation for "Modular Construction Products", the site name).
- Use Kentico's logging APIs to log success/failure/warning/information appropriately.
- Consider refactoring large methods and using abstraction layers to make code readable and reusable.
- Use built-in extensibility points such as global events or providers.
- Use an appropriate naming convention to avoid collisions with system objects, especially during upgrades/hotfixes (e.g. prefix things with an abbreviated version of the site/project name).
This applies to both editors and visitors. Your solutions should be built with ease of use in mind. Your editors will have an easier time keeping the site up to date, and your visitors will be more engaged.
Some examples of how you can create a good experience for editors and visitors are:
- Utilize widgets rather than web parts for personalization and/or AB testing to allow your editors to manage this themselves.
- Build integrations that require simple interaction or are automatically run.
- Utilize custom modules to extend the system in a complex way while maintaining a consistent and easy to use user interface for editors.
- Don't require more information than necessary from visitors.
- Provide visitors with a customized experience based on their history or context.
- Make it easy for visitors to fall into the pit of success.
- Consider page load times for visitors (the faster the better).
Projects are very rarely built once and never extended. Thinking about how a feature might need to be enhanced in the future can help save effort and time in the future.
However, do bear in mind that there is a need to balance the effort/time with the project's budget/timeline. Be sure to think about:
- Consider how data will grow and change in the future.
- Think about future integrations or features that need to be added.
Consider building on Kentico built in extensibility points to help with this process:
- The portal engine enables rapid development and flexibility.
- Use custom modules.
- Investigate event handlers.
- Look for providers to override/extend.
You should always verify that what you've built functions as intended. This includes negative testing to make sure that unintended behavior is guarded against. More details on this can be found in the Testing section.
Scenario: Adding a category page with personas and secured content
A partner is working on a template for an online magazine to list public and subscriber only articles in a category.Dependencies
The client requires that if a visitor logs in as a subscriber, they will see an additional set of subscriber only articles. Visitors will also see suggested articles based on personas and be able to subscribe to articles in a category via RSS.
- The articles and categories will need to be in place before building this template.
- RSS feed readers will need standardized RSS feeds in order to properly subscribe. The RSS feed web parts/controls will enable this with minimal effort.
- The article lists do not show all the fields that are defined in an article page type. Specify only required columns to reduce the amount of data retrieved from SQL.
- The page doesn't have any dynamic user input. Consider adding output caching with appropriate cache dependencies to further speed up page loads.
- Author information is externally referenced from the articles. Consider either a custom SQL query to retrieve both the article and the relevant author in one query or get author data separately and caching that separately.
- Consider paging content.
- Configure the subscriber only article list to only display to subscribers.
- Configure the main article list and RSS feed to check permissions.
- Make sure you sanitize the category when using it as it is going to come from the user via the URL (e.g. SQL injection through where clause, XSS by displaying on the page).
- Be sure to clearly label/identify web parts and control IDs so that it is clear what they are used for.
- Using the portal engine allows for the page to be changed/enhanced easily in the future.
- This page is entirely dynamic, so editors don't have to worry about updating the content.
- As performance was considered, visitors experience faster page loads.
- Visitors also see personalized content based on prior activity on the site, increasing delight.
- Be sure to test a variety of use cases, such as:
- Subscriber access
- Anonymous access
- Invalid category names
- Attempt SQL/XSS injection (either do benign attacks or perform on a separate copy)
- Category with no content
- Persona testing
- Test RSS
Scenario: Integrating with an existing authorization service
The online magazine project requires the use of an existing subscriber database. Subscribers will log in to the Kentico site using their existing credentials. When the visitor logs in, they will be authenticated against the external system.Dependencies
From a technical perspective, we'll add a global event handler ensuring external authentication.
- This will require the third party subscriber database. You will need to be able to gracefully handle the subscriber database not being available.
- The third party database will need to allow us to authenticate a user and retrieve their roles so that we can assign appropriate roles for permissions.
- It might be better to regularly update user roles and assignments on a scheduled basis rather than on login to prevent extra work on every login to update roles.
- Make sure the communication with the third party subscriber database is secure.
- Make sure that role import/assignment doesn't end up adding a subscriber to an editor/administrator role.
- Make sure to apply appropriate permissions to imported roles.
- As we are extending the built-in functionality we will want to make sure to do a few things:
- Store the custom files in a logical place (e.g. /App_Code/OMI/SubscriberAuthentication.cs, where OMI is an abbreviation for our client name Online Magazine Inc.).
- Prefix all imported roles so that they are easier to identify (e.g. OMS All Access, where OMS stands for Online Magazine Subscriber).
- Add appropriate event log entries for issues like failure to connect to the subscriber database.
- Consider using an API or abstraction layer to interface with the third party database rather than directly writing a lot of custom code in the authentication event handler.
- As additional roles may be added in the future, roles should be dynamically created/updated.
- Future updates may bring over additional profile information into Kentico.
- Editors/Administrators can use the built-in features for role permissions.
- Visitors do not have to change/update their account information just because a new web site was launched.
- Test logging in with:
- A pre-existing Kentico user/password
- A pre-existing subscriber user/password
- A pre-existing subscriber user with the wrong password
- A non-existent subscriber user/password
- Verify that roles are assigned and created properly.
- Verify that users are created and assigned to the site properly.
- Consider using automated tests to verify custom functionality automatically.
Scenario: Automatically importing content
Our online magazine project has a lot of content, but they also want to syndicate content from another service.Dependencies
As there is a lot of this content, it was decided that a custom module would be created to manage this on the site. This content needs to be automatically imported on a regular basis.
- This will require the third party syndication service. You will need to be able to gracefully handle the syndication service not being available.
- The syndication service will need to support us asking for content between certain dates.
- This will require enabling synchronization tasks for our custom class if we have web farms.
- You will need to use the most recent article to request only articles that are newer than that.
- Consider setting this up as an external scheduled task and perform the import on a separate server to reduce overhead on the main production server(s).
- Consider updating whatever caches you have set up with the new data.
- Make sure the communication with the syndication service is secure.
- Lock down the custom module to only those editor roles that need it.
- Provide editors with read only access to the custom module.
- Store authentication for third party service securely and make it editable in the web.config or settings keys.
- As we are extending built-in functionality we will want to make sure to do a few things:
- Store the custom files in a logical place (e.g. /App_Code/OMI/SyndicationImporter/, where OMI is an abbreviation for our client name Online Magazine Inc.).
- Keep the code for accessing the service and performing the Kentico import separated.
- Log descriptive events to the Kentico event log if errors occur.
- Consider using an API or abstraction layer to interface with the syndication service rather than directly writing a lot of custom code in the scheduled task.
- As additional syndication services may be added in the future, try to architect the scheduled task to accept parameters so that you can reuse the code rather than rewrite or copy the task code.
- Consider trying to support configurable batch importing.
- Editors don't have to worry about the content as it is imported automatically, and the custom module provides them with appropriate access to review/manage the imported content.
- Visitors see the syndicated content just like any other content.
- Consider using automated tests to verify custom functionality automatically.
- Verify that partial imports and aborted imports can be resumed.
- Verify that an unavailable syndication service is handled gracefully.
- Verify that duplicate content is not imported.