Skip to content

Instantly share code, notes, and snippets.

@ktownsend-personal
Last active May 12, 2024 20:52
Show Gist options
  • Save ktownsend-personal/fc7246d1b02952eb8d2474e720f69e1b to your computer and use it in GitHub Desktop.
Save ktownsend-personal/fc7246d1b02952eb8d2474e720f69e1b to your computer and use it in GitHub Desktop.
How to host classic ASP with your ASP.NET Core project

Host classic ASP in an ASP.NET Core 8 project

I have a situation where I need to migrate a very old classic ASP website gradually into an ASP.NET Core 8 website.

In my research I found many people asking how but never found a fully working example, so I want to share this for others.

If you end up using any of this, my only ask is that you link to this gist and give me some credit in your code for the next developer to discover... and of course tell me about how it saved your life in the gist comments ☺

Solution Summary:

  • add ISAPI handler in web.config for each file extension to process as classicASP
  • put classicASP files in wwwroot folder of your aspNetCore project
  • update #include references to add wwwroot to path
  • add rewrite rule to web.config to inject wwwroot to path of incoming requests
  • add rewrite rule to web.config to inject correct default page if default page is classicASP
  • launch Visual Studio as administrator and debug with IIS Express
  • add session sync if you need it: see my other gist

Challenges Solved:

  • ASP ISAPI engine expects URL to match the website's configured folder root, but aspNetCore uses a wwwroot subfolder
  • default document is handled by aspNetCore but we need it to be index.html instead
  • aspNetCore and classicASP have their own separate session state
  • ASP ISAPI engine requires elevated permissions in IIS Express

The secret sauce:

In web.config for the aspNetCore project:

See web.config file for full example.

  • if you need classicASP to serve your default page, add rewrite rule for default document to ensure the next rewrite rule catches it
      <rule name="default-classic-doc">
        <match url="^$" />
        <action type="Rewrite" url="index.html"/>
      </rule>
    
  • add rewrite rule for all file extensions you need processed by the classicASP engine to route to wwwroot folder because aspNetCore nests the static files in that subfolder rather than the normal root path configured in IIS for the website
      <rule name="wwwroot-classicasp" stopProcessing="true">
        <match url="([\S]+[.](asp|html|htm))" ignoreCase="true" />
        <action type="Rewrite" url="wwwroot/{R:1}" />
      </rule>
    
  • add ISAPI handlers for all file extensions you need processed by the classicASP engine (*.asp, *.html and *.htm in my case) in web.config prior to the aspNetCore handler
      <handlers>
        <add name="Classic ASP for *.asp" path="*.asp" verb="GET,HEAD,POST,MERGE,REPLACE,CLEAR,ABANDON" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" requireAccess="Script" />
        <add name="Classic ASP for *.htm" path="*.htm" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" requireAccess="Script" />
        <add name="Classic ASP for *.html" path="*.html" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" requireAccess="Script" />
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\yourWebsite.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />    
    

The classicASP project files:

  • put the classicASP files in wwwroot folder of the aspNetCore project
  • update all #include paths to add wwwroot so the classic ASP engine can find them

    example: <!-- #include virtual="/wwwroot/inc/sanitizer.asp" -->

    The ASP engine expects paths to be relative to the configured root of the website and doesn't benefit from the rewrite rules. You will get 500 errors on the classic pages if your includes aren't found; enable detailed errors in IIS to see what's going on.

Running with IIS Express via Visual Studio:

  • IIS Express requires elevated permission to run the ASP ISAPI engine, so you must run Visual Studio as administrator

    you will get 500 errors if you forget to run Visual Studio as administrator

Use classicASP session in aspNetCore:

<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<rewrite>
<rules>
<rule name="classic-default-doc">
<match url="^$" />
<action type="Rewrite" url="index.html"/>
</rule>
<rule name="classic-wwwroot" stopProcessing="true">
<match url="([\S]+[.](asp|html|htm))" ignoreCase="true" />
<action type="Rewrite" url="wwwroot/{R:1}" />
</rule>
</rules>
</rewrite>
<handlers>
<add name="Classic ASP for *.asp" path="*.asp" verb="GET,HEAD,POST,MERGE,REPLACE,CLEAR,ABANDON" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" requireAccess="Script" />
<add name="Classic ASP for *.htm" path="*.htm" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" requireAccess="Script" />
<add name="Classic ASP for *.html" path="*.html" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="%windir%\system32\inetsrv\asp.dll" resourceType="File" requireAccess="Script" />
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\yourWebsite.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>
</location>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment