DEV Community

Cover image for Kentico 12: Design Patterns Part 24 - Improving Our Projects with Configuration
Sean G. Wright
Sean G. Wright

Posted on

Kentico 12: Design Patterns Part 24 - Improving Our Projects with Configuration

Laying A Foundation

I've recently had some conversations with other developers about setting up and configuring projects.

I work ๐Ÿ‘ทโ€โ™‚๏ธ for a web development and marketing agency, WiredViews. Working for an agency involves a constant stream of greenfield projects, which means I've had lots of experience "starting" things.

Below I'd like to cover some recommendations for setting up a Kentico 12 MVC project and what benefits these bring.

This is going to be a 3-part post. In this post we're going to look at Documentation.

The previous posts were about Developer Experience and Documentation.

Let's begin!

Cat typing like a champ


Configuration

Configuration represents all the switches and buttons that toggle how our projects work, when we are developing, deploying, and running our apps.

Using HTTPS Locally

Trying to make our local development environments as much like the staging and production servers as possible is something that we developers always strive for.

Docker is great at solving this problem, but classic Full Framework .NET applications aren't the best use-case ๐Ÿ˜ž (unlike .NET Core, which works great with Docker).

Fortunately, there are configuration changes we can make to our Kentico 12 MVC code base to at least enable HTTPS for local development ๐Ÿ‘๐Ÿพ.

First, this can either be accomplished by running the site out of IIS locally or using IIS Express.

I've done both, but my recommendation is to use IIS Express, due to the way it's integrated with Visual Studio.

Now, if we open the .csproj files for both the Content Delivery (MVC) and Content Management (CMS) applications, we can make sure we have all the settings correctly defined.

Inside the first <Project><PropertyGroup> node, we'll want to set 2 properties:

<Project ...>
  <Import ...>
  <PropertyGroup>
    <UseIISExpress>true</UseIISExpress>
    <IISExpressSSLPort>44325</IISExpressSSLPort>
Enter fullscreen mode Exit fullscreen mode

We can set the <IISExpressSSLPort> to whatever we want, as long as its in the 44300 to 44399 range.

We will want different values here for the 2 different web application .csproj files (example: 44325 and 44326).

Next, we need to define some Visual Studio configuration in the <Project><ProjectExtensions> node:

<Project ...>

  <!-- Lots of other stuff -->

  <ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
        <WebProjectProperties>
          <UseIIS>True</UseIIS>
          <AutoAssignPort>True</AutoAssignPort>
          <DevelopmentServerPort>51872</DevelopmentServerPort>
          <DevelopmentServerVPath>/</DevelopmentServerVPath>
          <IISUrl>https://localhost:44325/</IISUrl>
          <NTLMAuthentication>False</NTLMAuthentication>
          <UseCustomServer>False</UseCustomServer>
          <CustomServerUrl>
          </CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
        </WebProjectProperties>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>
Enter fullscreen mode Exit fullscreen mode

Here we can set the <DevelopmentServerPort> (HTTP) value to whatever we want, typically in the 50000-59999 range, and the <IISUrl> to be https://localhost: plus the port we picked for <IISExpressSSLPort>.

Do this for both the Content Management and Content Delivery applications and open up the solution in Visual Studio.

When we run the apps we should be able to load them over https:// using the ports we defined ๐Ÿ‘๐Ÿพ.

Running https:// locally can be great for catching Mixed Content Warnings early in the development process ๐Ÿ˜€ or testing HSTS.


Using <PackageReference> for NuGet

The Kentico Installation Manager can be used to create new applications or update existing ones.

When creating a new Kentico 12 MVC application, we are given 2 ASP.NET projects - one for content management (the classic CMS application) and one for content delivery (the MVC application).

Both are created using the outdated (but still functional) packages.config style of NuGet package management ๐Ÿ˜‘.

.NET Core uses <PackageReference>, which I've written about in my post Kentico 12 Class Libraries with Modern .NET Core Features.

Read about the benefits of <PackageReference> in Microsoft's documentation ๐Ÿง!

Unfortunately, Visual Studio 2019 no longer supports migrating packages.config to <PackageReference> for ASP.NET projects ๐Ÿ™๐Ÿพโ€โ™€๏ธ.

Fortunatley, we can trick Visual Studio into thinking our project is just another C# class library ๐Ÿ˜ฎ!

If we open up the .csproj for one of our projects, we can see an MSBuild property <ProjectTypeGuids>:

<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
Enter fullscreen mode Exit fullscreen mode

Using a reference for these identifiers we can see that 349c5851-65df-11da-9384-00065b846f21 represents an ASP.NET project and fae04ec0-301f-11d3-bf4b-00c04f79efbc represents a C# project.

Let's temporarily replace with <ProjectTypeGuids>:

<ProjectTypeGuids>{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
Enter fullscreen mode Exit fullscreen mode

Now our project is no longer seen as an ASP.NET project by Visual Studio and we'll see the "Migrate" option when right clicking the packages.config file.

Visual Studio solution explorer right click context menu on the  raw `packages.config` endraw  file

We can perform the migration and be one step closer to an ASP.NET Core project - no more needing to manage .NET Framework version for packages or have all the transitive dependencies enumerated our packages list ๐Ÿ’ช๐Ÿฝ!

Once complete we need to make sure to revert the <ProjectTypeGuids> to the original value so that Visual Studio lights up with the correct ASP.NET features we've come to expect for our project.


Web.config transforms for production

When working on our project locally we might have all our configuration defined in the web.config - connection strings, app settings, URL Rewrite rules, debug flags...

But what happens when we deploy our application to another environment where some of these values should change ๐Ÿค”?

Our first approach might be changing the values manually each time we deploy, but this is error prone and requires an additional deployment step (doubly error prone ๐Ÿ˜ฑ!)

A better option is to use the web.config transforms functionality that is built into MSBuild and Visual Studio.

Assume we have a web.config with the following configuration:

<system.web>
    <compilation debug="true" targetFramework="4.7.2"/>

<!-- ... -->
Enter fullscreen mode Exit fullscreen mode

We want the debug="true" locally because we want to hit breakpoints in Visual Studio correctly when running our site.

Then, when we deploy the app to any environment where we are running it outside of Visual Studio, we want to remove that attribute because of the significant performance impact it can have.

In a new ASP.NET project we should be able to right-click the web.config file, in the Solution Explorer in Visual Studio, and see the "Add Config Transform" option.

Click this will add a new file that is a set of instructions to "transform" the web.config for a specific build configuration (eg: Debug vs Release).

Visual Studio solution explorer right click context menu on the  raw `web.config` endraw  file

After adding the transform we can see (2) new files - web.Debug.config and web.Release.config:

Visual Studio solution explorer showing the  raw `web.Debug.config` endraw  and  raw `web.Release.config` endraw  nested under a  raw `web.config` endraw  file

Opening up the web.Release.config we can see that Visual Studio has already done us a favor by adding the transform instruction to remove the debug attribute when publishing the app using the Release configuration ๐ŸŽ‰.

 <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
Enter fullscreen mode Exit fullscreen mode

Now, whether we are publishing to the local filesystem, IIS on a virtual machine, or an Azure App Service, we can be sure our deployed web.config will have the right values for that environment ๐Ÿ‘๐Ÿผ.

If you want to learn more about how to "publish" an ASP.NET application from Visual Studio, check out the official Microsoft documentation.

AppSettings.Local.config

Another way we can take advantage of web.config transforms is with our app settings (and similarly, connection strings).

We don't want to commit sensitive settings into source control, and other team members might want their own local settings ๐Ÿ™„.

We can create local configuration files that are set as the default paths in our web.config and then transform these values to the normal, committed files when publishing.

Here's an example of what the base web.config looks like:

Notice, there's no sensitive values or ones other developers might want to configure here.

<appSettings file="App_Config\AppSettings.Local.config">
    <add key="webpages:Version" value="3.0.0.0"/>
    <add key="webpages:Enabled" value="false"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    <add key="aspnet:MaxJsonLength" value="20971520"/>
</appSettings>
<connectionStrings configSource="App_Config\ConnectionStrings.Local.config"/>
Enter fullscreen mode Exit fullscreen mode

The App_Config\AppSettings.Local.config and App_Config\ConnectionStrings.Local.config are both ignored by source control and also not included in the .csproj.

Local config files excluded from the project in Visual Studio solution explorer

They include the sensitive and customizable values we use locally when developing ๐Ÿ˜‰:

<appSettings>
  <add key="CMSHashStringSalt" value="..."/>

  <add key="CMSAzureAccountName" value="..."/>

  <add key="logging:serilog:log-level" value="Debug" />
Enter fullscreen mode Exit fullscreen mode

The web.Release.config then contains a transform instruction to point the source of our settings and connection strings to other files:

<appSettings
    file="App_Config\AppSettings.config"
    xdt:Transform="SetAttributes(file)">
</appSettings>
<connectionStrings 
    configSource="App_Config\ConnectionStrings.config"
    xdt:Transform="SetAttributes(configSource)" />
Enter fullscreen mode Exit fullscreen mode

These two files (App_Config\AppSettings.config and App_Config\ConnectionStrings.config) are both included in the .csproj and source control, but they don't include any sensitive values ๐Ÿคจ.

Visual Studio solution explorer showing 2 sets of settings files

Instead they are either empty (settings could be defined in an Azure App Service directly) or contain tokens that can be replaced by a continuous delivery tool or extension).

URL Rewrite Redirect to CMS Admin

Another cool use of web.config transforms is changing the value of a URL Rewrite rule:

This rule would be added to our Content Delivery application (MVC) web.config.

It says any request for /admin should be redirected to the Content Management application (CMS) which can be found at https://localhost:44326/admin locally ๐Ÿค“.

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Admin-Redirect">
        <match url="^admin"/>
        <action type="Redirect" url="https://localhost:44326/admin"/>
      </rule>
    </rules>
  </rewrite>

<!-- ... -->
Enter fullscreen mode Exit fullscreen mode

However, in production that domain is different. This means in our web.Release.config we have a transform for this URL rewrite rule.

<system.webServer>
  <rewrite>
    <rules>
      <rule xdt:Transform="Replace" xdt:Locator="Match(name)"
            name="Admin-Redirect">
        <match url="^admin"/>
        <action type="Redirect" 
            url="https://admin.your-domain.com/admin"/>
      </rule>
    </rules>
  </rewrite>

<!-- ... -->
Enter fullscreen mode Exit fullscreen mode

I like this solution a lot more ๐Ÿ˜Ž than the one recommended in the Kentico documentation that performs the redirect at the ASP.NET level instead of the IIS level.

Less code, more performant ๐Ÿ’ช๐Ÿฟ!


Conclusion

In this post we looked at the many ways we can improve our Kentico 12 MVC projects by adjusting how they are configured. .csproj settings, NuGet package management, and web.config transforms.

Much of this configuration can be found 'behind the scenes' in an ASP.NET project, which is both good and bad. We don't need to worry about it when getting started (good ๐Ÿ‘!) but we also might not know it's there when we need to customize it (not so good ๐Ÿ‘Ž!).

None of these things are Kentico specific, but if we are new to Kentico or .NET, these suggestions might also be new and helpful.

Hopefully this post pulls back the curtain some and encourages you to explore how you can configure your Kentico 12 MVC project to work better for you and your team.

...

As always, thanks for reading ๐Ÿ™!


Photo by Oscar Nord on Unsplash

We've put together a list over on Kentico's GitHub account of developer resources. Go check it out!

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

#kentico

Or my Kentico blog series:

Top comments (0)