loading...
Cover image for Kentico 12: Design Patterns Part 18 - Preparing for Kentico 2020

Kentico 12: Design Patterns Part 18 - Preparing for Kentico 2020

seangwright profile image Sean G. Wright ใƒป9 min read
Photo by Olesya Grichina on Unsplash

Kentico 2020: The Phoenix and .NET Core

The next version of Kentico EMS, which will be Kentico 2020 and has a pre-production name of "Phoenix", will usher in a new era for Kentico ๐Ÿค—.

Kentico's Portal Engine development architecture will be removed completely, Kentico's core libraries will target .NET Standard 2.0, and Kentico itself will support .NET Core (and therefore ASP.NET Core) ๐Ÿ‘.

These are some major changes (and depending on your perspective, bigger than Kentico 12's move to ASP.NET MVC 5).

Kentico 2020 will likely be released, with a full suite of features, in November of 2020 (if past releases set any precedent).

But why, you ask, is Sean writing about Kentico 2020 when this blog series is about Kentico 12 ๐Ÿค”?!

Well there is a pretty simple answer. Unless we want our Kentico 12 sites to always run on Kentico 12, at some point, we will be upgrading them to Kentico 2020.

Below, I'd like to detail some recommendations to prepare all of us for that eventual effort, laying the groundwork now to help our future selves look back on us with kinder eyes ๐Ÿ˜Š.


Adopt Kentico + MVC

Since Kentico 2020 won't support Portal Engine, building a site in Portal Engine with Kentico 12 means that there isn't going to be an upgrade path - using Portal Engine today is a non-starter (unless you don't plan on upgrading).

If you haven't adopted the awesome Kentico 12 + MVC combo, check out Kentico's documentation on using MVC and all the other blog posts in this series on Kentico 12 Design Patterns.

At this point, Kentico 12 has been out for well over a year, so there are many other Kentico developers writing blog posts about their experiences with MVC, and the community on DevNet is always happy to help ๐Ÿ’ช.


Don't Rely on Removed Kentico EMS Features

Along with Portal Engine development, Kentico EMS is going to be removing several other features in Kentico 2020.

Most of the features are strongly tied to Portal Engine development, so if we are doing Kentico 12 + MVC then we probably don't have much to worry about.

But we should be familiar with the list anyway to save ourselves some heartache ๐Ÿ’” later.

There's also been discussions of "Related Pages" potentially being removed in Kentico 14 (or whatever comes after Kentico 2020). This is definitely not set in stone, but knowing this kind of stuff well in advance is a great reason to frequent DevNet and follow Kentico on Twitter to stay in-the-know ๐Ÿ˜‰.


Write MVC 5 Code Like It's ASP.NET Core

Although a lot looks the same when comparing MVC 5 running on ASP.NET to ASP.NET Core, there are many things that have changed.

While we could go looking for the new ASP.NET Core-ish way of doing things when we upgrade our code, it might be easier to do this ahead of time.

Don't Use System.Web.Optimization

When it comes to managing client-side dependencies in ASP.NET MVC 5, the standard approach has been to leverage the types found in the System.Web.Optimization namespace.

However, that code hasn't been updating since 2014 and both CSS and JavaScript have changed significantly since then.

I've run into cases where MVC started throwing exceptions (when trying to bundle and minify) because it couldn't understand my modern ES2015+ JavaScript, despite the fact that Edge/Chrome/Firefox/Safari all ran it without issue ๐Ÿ˜ฃ.

Avoid the types in this namespace where possible and adopt alternative approaches to managing client-side dependencies, like the ones I mention in my post about managing front-end dependencies or Vue.js with Kentico 12 below ๐Ÿค“.

Use Dependency Injection / IoC Container

While MVC 5 supports Dependency Injection using a custom Inversion of Control (Ioc) Container like Autofac, ASP.NET Core requires it for framework types and strongly encourages it for developer's custom code ๐Ÿ˜ฎ.

Kentico's MVC 5 documentation explains Dependency Injection and how to set it up, so we already have all the tools we need to get started down this path, today ๐Ÿ‘.

Note: We can even add Dependency Injection to the CMS, check out my blog post Kentico 12: Design Patterns Part 4 - Adding Dependency Injection to the CMS to find out how ๐Ÿง.

Use async/await Where Possible

While MVC 5 supports C#'s async/await syntax (which leads to performance gains when handling many HTTP requests concurrently), it's kinda apparent that support was added after-the-fact.

ASP.NET Core, however, takes a async/await-first approach from the beginning ๐Ÿ’ช!

This means that it's no longer a question of worrying about synchronous calls to async code resulting in deadlocks ๐Ÿ˜ฑ.

Async code should be async from top to bottom, and since ASP.NET Core allows and encourages developers to adopt this pattern, let's do it where it brings easy wins.


It should be noted that sometimes we have to use what we're given and we need to rely on what's provided in ASP.NET MVC 5, even though we know it's not there in ASP.NET Core.

For these scenarios there's another option...


Isolate ASP.NET Behind Abstractions

The move to MVC for Kentico 12 has brought about a lot of new framework features to leverage, NuGet packages to consume, and namespaces to add usings for.

These parts of MVC are great because they help us get our work done, but they are a double-edged sword - they can be a liability ๐Ÿ˜•.

ASP.NET MVC 5 was built on System.Web and a large part of the original motivation behind ASP.NET Core was to get away from System.Web (it was modeled after ASP.NET Web API's independence of System.Web using OWIN ๐Ÿคฏ).

This means any code that relies on System.Web could see its types moved, or worse, removed in ASP.NET Core โ˜น.

A lot of MVC 5 features are still in ASP.NET Core, but because of the changes, my advice is to put your use of ASP.NET specific types behind abstractions.

What would this look like ๐Ÿค”?

Classes like System.Web.UrlHelper, System.Web.Routing.RouteCollection, and especially System.Web.HttpContext can be put behind custom interfaces that we create, instead of being spread throughout our codebase.

Below is an example:

public interface IUrlBuilder
{
    string BuildUrl(
        string actionName, 
        string controllerName,
        object routeValues);
}

public class MVCUrlBuilder : IUrlBuilder
{
    public string BuildUrl(
        string actionName, 
        string controllerName,
        object routeValues)
    {
        var requestContext = HttpContext.Current.Request.RequestContext;

        var urlHelper = new UrlHelper(requestContext);

        return urlHelper.Action(
            actionName, 
            controllerName, 
            routeValues, 
            Uri.UriSchemeHttps);
    }
}

This might seem like a weird thing to do since we created a new interface and class to do the same things that UrlHelper already did.

However, if we use this interface (along with Inversion of Control and Dependency Injection) throughout our codebase, we've removed a dependency on UrlHelper and HttpContext (both of which are in System.Web) ๐ŸŽ‰.

As a side bonus, by removing dependencies on things like HttpContext, our code becomes a lot more unit testable ๐Ÿ’ช.

I cover this topic further in my blog post Kentico 12: Design Patterns Part 1 - Writing Testable Code.


Write Automated Integration and End-to-End Tests

On the topic of tests, an upgrade from ASP.NET MVC 5 to ASP.NET Core is likely going to involve a lot of moving pieces, especially if it's being performed at the same time as a Kentico upgrade.

How can we ensure that our app's behavior still reflects the expectations of the stakeholders? How can we make this kind of change without disrupting the business and site visitors, from a functionality perspective ๐Ÿคทโ€โ™‚๏ธ?

Integration tests can go a long way towards ensuring that business logic behavior is well defined, the units of our code play nice together, and this verification can be automated and reproducible ๐Ÿ˜‰.

If we need more guarantees, end-to-end (E2E) tests can prove that the sign-up form or checkout experience is functioning as required, despite the fact that we've just pulled the framework-as-tablecloth out from underneath the dishes.

This is how we want things to go

Never written an integration test? Learn how in my post Kentico 12: Design Patterns Part 8 - Setting Up Integration Tests.


Check Our NuGet Dependencies For Compatibility

.NET Standard 2.0 and ASP.NET Core have been out for a little while now (ASP.NET Core is currently at version 3.1) and a large part of the .NET community has updated their libraries and tools to support these newer targets.

However, since the adoption of ASP.NET Core is likely to be a new thing for a lot of Kentico developers, there could be some skeletons in our closets - libraries that are no long maintained or haven't yet been upgraded.

The last thing we want to happen is, halfway through a Kentico upgrade, realize that the library we depend on can't come with us, due to incompatibility, and needs to be replaced ๐Ÿ˜ž.

So, we can check our dependencies now and plan for the future with alternatives if necessary ๐Ÿ‘.


Updating Our Internal Libraries

In addition to external library dependencies, we are probably using some libraries that we've written ourselves.

As library authors, there's a couple things that we can do to help prepare for a future of Kentico 2020 built with ASP.NET Core.

Migrate to the SDK-Style .csproj Format

Along with the changes to the runtime and frameworks, the move to .NET Core brings changes to the tooling.

One that many developers will probably notice is the update to the .csproj file that defines a .NET project. This new .csproj format is called is related to the new Common Project System for .NET and is often referred to as SDK-Style ๐Ÿค”.

Initially this change was delivered as something specific to .NET Core, but it is also supported for .NET Framework class libraries.

Last year, in my post Kentico 12 Class Libraries with Modern .NET Core Features, I detailed how Kentico developers can start leveraging the new .csproj now ๐Ÿ˜Ž.

My favorite way to do this is using Hans van Bakel's CsprojToVs2017 library, however you can also watch this video from Scott Hanselman or perform the upgrade directly in Visual Studio.

The new .csproj brings many quality-of-life changes for developers, which means it's not just a technical change with no benefit.

There's an old proverb I'm reminded of...

"The best time to update to the SDK-Style project was 3 years ago. The second best time is now" - Sean G. Wright ๐Ÿคฃ

Target .NET Standard 2.0 In Our Libraries

While we're updating the project format, we might as well update the target framework!

Since the interop between .NET Core and .NET Framework has lots of sharp edges, and since we can't use System.Web with ASP.NET Core, upgrading our libraries to .NET Standard 2.0 is a great next step.

Microsoft provides a "portability analyzer" that can show the bits of framework not supported in a library if it were to be upgraded to .NET Core ๐Ÿ™‚.

If we've managed to isolate those ASP.NET types that don't exist in ASP.NET Core, we might be able to update our libraries without downstream consumers (our Kentico applications) being effected ๐Ÿ˜.


In Review

Preparing our Kentico applications for Kentico 2020 can seem daunting! It very well might be if we're tasked with it next year and we didn't formulate a plan.

However, there are several things we can do to put ourselves and our code in the best place possible when that upgrade day comes.

  • Adopt Kentico + MVC instead of Portal Engine
  • Identify which Kentico EMS features are being removed in Kentico 2020
  • Write our MVC 5 code like it's ASP.NET Core
    • Avoid System.Web.Optimization
    • Leverage Dependency Injection
    • Use async/await from the top -> down in our applications
  • Isolate ASP.NET specific types behind abstractions when we need to use them
  • Ensure consistent application behavior after upgrades with automated integration and end-to-end tests
  • Check 3rd part NuGet dependencies for ASP.NET Core compatibility
  • Update our internal libraries
    • Migrate to SDK-Style .csproj files
    • Target .NET Standard 2.0 where possible

Wow, that was a lot! If you haven't read any of my Kentico blog posts before, this could be like drinking from the firehose ๐Ÿš’๐Ÿ”ฅ๐Ÿ‘จโ€๐Ÿš’.

Fortunately we still have time, before Kentico 2020 is out, to adopt the things I mentioned in this blog post. Maybe it will make for a good starting point to plan your upgrade strategy ๐Ÿ‘!

As always, thanks for reading ๐Ÿ™!


If you are looking for additional Kentico content, checkout the Kentico tag here on DEV:

Or my Kentico blog series:

Posted on by:

seangwright profile

Sean G. Wright

@seangwright

dev lead @WiredViews, founding partner @craftbrewingbiz. @Kentico Xperience MVP. love to learn / teach web dev & software engineering, collecting vinyl records, mowing my lawn, craft ๐Ÿบ

Discussion

pic
Editor guide
 

It is a great honor to have you write about Kentico product versions and concepts in such detail, you are very deserving of the Kentico 2020 "MVP" title.