Kentico 12: Design Patterns Part 24 - Improving Our Projects with Configuration
Tags: kentico, aspnet, mvc, cms
Published: 2020-06-03 14:14:38

---
title: Kentico 12: Design Patterns Part 24 - Improving Our Projects with Configuration
published: true
description: Learn how to improve the configuration of a Kentico 12 MVC project.
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/0r9003gzp4g3vp9bnbc5.jpg
tags: kentico, aspnet, mvc, cms
series: Kentico 12 - Design Patterns
---

## 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](https://www.wiredviews.com/). 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](https://dev.to/seangwright/kentico-12-design-patterns-part-22-improving-our-projects-for-developer-experience-1jjk) and [Documentation](https://dev.to/seangwright/kentico-12-design-patterns-part-23-improving-our-projects-with-documentation-pfp).

Let's begin!

![Cat typing like a champ](https://media.giphy.com/media/uzglgIsyY1Cgg/giphy.gif)

---

# 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](https://www.docker.com/) 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:

```xml
<Project ...>
  <Import ...>
  <PropertyGroup>
    <UseIISExpress>true</UseIISExpress>
    <IISExpressSSLPort>44325</IISExpressSSLPort>
```

We can set the `<IISExpressSSLPort>` to whatever we want, as long as its [in the 44300 to 44399 range](https://docs.microsoft.com/en-us/iis/extensions/using-iis-express/handling-url-binding-failures-in-iis-express#overview).

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:

```xml
<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>
```

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](https://developers.google.com/web/fundamentals/security/prevent-mixed-content/fixing-mixed-content) early in the development process 😀 or testing [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security).

---

## Using `<PackageReference>` for NuGet

The [Kentico Installation Manager](https://docs.kentico.com/k12sp/external-utilities/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](https://docs.microsoft.com/en-us/nuget/reference/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_.

{% post seangwright/kentico-12-class-libraries-with-modern-net-core-features-34n5 %}

> Read about [the benefits](https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference) 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>`:

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

Using [a reference](https://stackoverflow.com/a/28911360/939634) 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>`:

```xml
<ProjectTypeGuids>{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
```

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 `packages.config` file](https://dev-to-uploads.s3.amazonaws.com/i/c2rf7r74ub671h1zcx0h.jpg)

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:

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

<!-- ... -->
```

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](https://www.hanselman.com/blog/MostCommonASPNETSupportIssuesReportingFromDeepInsideMicrosoftDeveloperSupport.aspx).

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 `web.config` file](https://dev-to-uploads.s3.amazonaws.com/i/c1v9nbgvccsyw2se3po6.jpg)

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

![Visual Studio solution explorer showing the `web.Debug.config` and `web.Release.config` nested under a `web.config` file](https://dev-to-uploads.s3.amazonaws.com/i/hontjua6lh8v1v9oim96.jpg)

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 🎉.

```xml
 <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
```

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](https://docs.microsoft.com/en-US/visualstudio/deployment/quickstart-deploy-to-a-web-site?view=vs-2019).

### 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.

```xml
<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"/>
```

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](https://dev-to-uploads.s3.amazonaws.com/i/aaytkeyvmgkva3l3ozw4.jpg)

They include the sensitive and customizable values we use locally when developing 😉:

```xml
<appSettings>
  <add key="CMSHashStringSalt" value="..."/>
  
  <add key="CMSAzureAccountName" value="..."/>

  <add key="logging:serilog:log-level" value="Debug" />
```

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

```xml
<appSettings
    file="App_Config\AppSettings.config"
    xdt:Transform="SetAttributes(file)">
</appSettings>
<connectionStrings 
    configSource="App_Config\ConnectionStrings.config"
    xdt:Transform="SetAttributes(configSource)" />
```

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](https://dev-to-uploads.s3.amazonaws.com/i/25kumxz8bja4lkn53hh7.jpg)

Instead they are either empty (settings could be defined in an [Azure App Service](https://docs.microsoft.com/en-us/azure/app-service/configure-common) directly) or contain tokens that can be replaced by [a continuous delivery tool](https://octopus.com/docs/deployment-process/configuration-features/xml-configuration-variables-feature) or [extension](https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens)).

### URL Rewrite Redirect to CMS Admin

Another cool use of `web.config` transforms is changing the value of a [URL Rewrite](https://www.iis.net/downloads/microsoft/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 🤓.

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

<!-- ... -->
```

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

```xml
<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>

<!-- ... -->
```

I like this solution a lot more 😎 than the one recommended in the [Kentico documentation](https://docs.kentico.com/k12sp/developing-websites/starting-with-mvc-development/adding-an-administration-redirect-to-mvc-sites) 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 🙏!

---

<figcaption>Photo by <a href="https://unsplash.com/@furbee">Oscar Nord
</a> on <a href="https://unsplash.com">Unsplash</a></figcaption>

---

We've put together a list over on [Kentico's GitHub account](https://github.com/Kentico/Home/blob/master/RESOURCES.md) of developer resources. Go check it out!

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

{% tag kentico %}

Or my Kentico blog series:

- [Kentico EMS: MVC Widget Experiements](https://dev.to/search?q=kentico%20ems%3A%20mvc%20widget%20experiements)
- [Kentico 12: Design Patterns](https://dev.to/search?q=Kentico%2012%3A%20Design%20Patterns)
- [Kentico CMS Quick Tips](https://dev.to/search?q=Kentico%20CMS%20Quick%20Tip)