When an ASP.NET application moves from .NET Framework to ASP.NET Core, only part of its web.config becomes appsettings.json: the app settings and connection strings. Everything else in the file either becomes code in Program.cs, moves to the host, belongs to a library, or disappears because the feature it configured no longer exists. This guide is for the developer doing that move and for the IT manager who wants to know how much of it there is before the work is planned.
It assumes the target is .NET 10, the current long-term support release, supported until 14 November 2028. Our .NET Framework to .NET 10 migration guide covers the rest of the job.
Why the file cannot simply be copied
On .NET Framework, web.config does two jobs at once. It holds the application’s own settings, and it configures IIS and the ASP.NET pipeline itself: authentication, session state, error pages, request limits, modules and handlers. ASP.NET Core separates these. Settings are read from appsettings.json, environment variables and other providers. The pipeline is built in code, in Program.cs, as a list of middleware.
So a web.config built up over many years is really a list of decisions, some of them forgotten. The move is the moment each one has to be found and made again, on purpose.
What goes wrong when it is done by hand
- Settings read in code that nobody remembers.
ConfigurationManager.AppSettings["X"]can be called from anywhere, including class libraries. If a key is missed, the application starts and fails later, on the one screen that used it. - Secrets end up in source control. web.config files often hold passwords in connection strings, SMTP settings and API keys. Copied straight into appsettings.json, they get committed with the code.
- Behaviour changes silently. A request size limit, a session timeout, a culture setting or a custom error page that was set in web.config falls back to the ASP.NET Core default if nobody carries it over. Nothing fails at build time.
- Transforms are forgotten. Web.Release.config and other transform files hold the real production values. Converting only the base file gives an application that works on a developer’s machine and not on the server.
- IIS rules are lost. URL Rewrite rules, custom headers and MIME types under system.webServer are easy to overlook because they never appear in the code.
Doing it by hand: the steps
- Collect every config file. The base web.config, every transform, and any files it points to with
configSourceorfileattributes. Note which environment each transform belongs to. - Find every place settings are read. Search the whole solution for
ConfigurationManager,WebConfigurationManagerandConnectionStrings. That list, not the file, tells you which settings are live. - Move app settings and connection strings. App settings become keys in appsettings.json; keys written as
Section:Namebecome nested sections. Connection strings go under aConnectionStringssection, read withGetConnectionString("Name"). Replace eachConfigurationManagercall with injected configuration, ideally bound to a typed options class. - Take the secrets out. Blank passwords and keys in appsettings.json. Use user secrets on developer machines and environment variables or a secrets store on the server. In environment variable names, a double underscore stands for the colon, so
Smtp:PasswordbecomesSmtp__Password. - Rebuild system.web in Program.cs. Each section has a replacement: forms authentication becomes cookie authentication;
customErrorsbecomes the exception handler and status code pages middleware;sessionStatebecomes the session middleware with a cache behind it;globalizationbecomes request localisation;machineKeybecomes Data Protection; HTTP modules and handlers become middleware. Membership providers have no direct equivalent and need a decision, usually ASP.NET Core Identity. - Deal with system.webServer. Rewrite rules can be saved as a separate XML file and loaded by ASP.NET Core’s rewrite middleware with
AddIISUrlRewrite. Static file MIME types, custom headers and request limits become middleware or server options. If the site will still run on IIS, the published web.config stays for the hosting module, and IIS-level settings such asmaxAllowedContentLengthcan stay there too. - Drop what no longer applies. Assembly binding redirects, compilation settings, trust levels and
httpRuntime targetFrameworkhave no meaning on modern .NET. - Carry the transforms over. Each transform’s differences go into
appsettings.Production.jsonor the matching environment file, chosen by theASPNETCORE_ENVIRONMENTvariable. - List the custom sections. Sections registered under
configSectionsbelong to libraries such as log4net, Unity or Quartz. Each library documents its own setup on modern .NET, and some have no modern version at all.
The checks before you call it done
- Every key found in step 2 exists in the new configuration, or has been deliberately dropped.
- No password or key is committed in any appsettings file.
- Upload limits, timeouts and session lengths match the old values, or the change is agreed.
- Error pages, redirects and security headers behave the same, checked against the live site.
- The application starts with production settings in a test environment, not only on a developer machine.
The shortcut
We built the free web.config to appsettings.json converter to do the mechanical part of this. Paste a web.config and it produces the appsettings.json, with secrets blanked and listed, the rewrite rules as a separate file, and a note for every other section saying where it goes, with Program.cs code where the mapping is direct. It runs in your browser and the file is not sent anywhere.
It does not replace steps 2, 8 and 9: it cannot see your code, apply transforms or configure third-party libraries. What it gives is a complete list of what the file contains and what each part becomes, which is the starting point for the estimate and the work.
For an application with many projects, also check the packages before starting: the NuGet upgrade planner checks each package for a release that supports modern .NET.
The converter is free, with no account or sign-up: web.config to appsettings.json converter.