0

I am hosting Dotnet Core 3.1 project with a Vue js application. For that, I have hosted the vue js static files inside the www-root folder.

I also have a swagger UI in my application.

This is the default web config that I have in the hosted directory.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false" 
                stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
  </system.webServer>
</configuration>

With this configuration, the swagger ui runs fine without any error.

But I have to add the rewrite logic for the Vue js application, so I have updated the web config with the following configuration.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="wwwroot-static" stopProcessing="true">
          <match url="([\S]+[.](html|htm|svg|js|css|png|gif|jpg|jpeg))" />
          <action type="Rewrite" url="wwwroot/{R:1}" />
        </rule> 

        <rule name="empty-root-index" stopProcessing="true">
          <match url="^$" />
          <action type="Rewrite" url="wwwroot/index.html" />
        </rule>

        <!-- 
             Make sure you have a <base href="/" /> tag to fix the root path 
             or all relative links will break on rewrite 
        -->
        <rule name="AngularJS-Html5-Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                <add input="{REQUEST_URI}" pattern="^/.well-known/openid-configuration" negate="true" />
                <add input="{REQUEST_URI}" pattern="^/.well-known/jwks" negate="true" />
                <add input="{REQUEST_URI}" pattern="^/api(.*)" negate="true" />
                <add input="{REQUEST_URI}" pattern="^/swagger(.*)" negate="true" />
                <add input="{REQUEST_URI}" pattern="^/account(.*)" negate="true" />
                <add input="{REQUEST_URI}" pattern="^/connect(.*)" negate="true" />
          </conditions>
          <action type="Rewrite" url="wwwroot/index.html"  />
        </rule> 
      </rules>
    </rewrite>

    <handlers>
      <add name="StaticFileModuleHtml" path="*.htm*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModuleSvg" path="*.svg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModuleJs" path="*.js" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModuleCss" path="*.css" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModuleJpeg" path="*.jpeg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModuleJpg" path="*.jpg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModulePng" path="*.png" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="StaticFileModuleGif" path="*.gif" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false" 
                stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
  </system.webServer>
</configuration>

With this configuration in the web config, my vue js application runs fine. But then when I go the site: http(s)://[MYWEBAPP]/swagger, it redirects to http(s)://[MYWEBAPP]/swagger/index.html and gives a 404 files not found error.

Configure Service in my startup class looks like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Sample API")
    );

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
        
    app.UseHttpsRedirection();
    
    app.UseStaticFiles();
    app.UseRouting();
    
    app.UseAuthentication();  
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
       endpoints.MapControllerRoute(
       name: "default",
       pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Trying through the multiple available solutions, I realized that the swagger UI is trying to look for the index.html from the wwwroot, so it is causing the not found error. I am stuck on how to suggest swagger UI to look into the own directory.

What could be the issues with this? What am i missing here? Anyone else also might have this issue?

Rasik
  • 1,961
  • 3
  • 35
  • 72
  • were you able to fix the issue? I know its because of the handlers. But handlers are required for spa to work. I have tried the solution mentioned here https://stackoverflow.com/questions/48889816/iis-rewrite-exclude-folders-and-subfolders-swagger-case/48893301#48893301 but still no luck – saif iqbal Jul 07 '22 at 16:37
  • I have also tried the same, but no luck. – Rasik Jul 09 '22 at 03:27

1 Answers1

0

I was struggling with the same problem with my React application. To pass swagger request to .Net application IIS has to do following:

  1. Not rewrite URL starting with swagger
  2. Select correct handler based on its path attribute

My web.config looks similar to this xml. Important is first rewrite rule and handler for swagger/* path.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <rewrite>
        <rules>
          <rule name="swagger" stopProcessing="true">
            <match url="swagger/.*" />
          </rule>

          <rule name="HTTPS force" enabled="false" stopProcessing="true">
            <match url="(.*)" />
            <conditions>
              <add input="{HTTPS}" pattern="^OFF$" />
            </conditions>
            <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
          </rule>

          <rule name="wwwroot-static" stopProcessing="true">
            <match url="([\S]+[.](.+))" />
            <action type="Rewrite" url="wwwroot/{R:1}" />
          </rule>

          <rule name="empty-root-index" stopProcessing="true">
            <match url="^$" />
            <action type="Rewrite" url="wwwroot/index.html" />
          </rule>

          <rule name="React-Html5-Routes" stopProcessing="true">
            <match url=".*" />
            <conditions logicalGrouping="MatchAll">
                            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                            <add input="{REQUEST_URI}" pattern="api/(.*)" negate="true" />
            </conditions>
            <action type="Rewrite" url="wwwroot/index.html" />
          </rule>
        </rules>
      </rewrite>

      <handlers>
        <add name="aspNetCoreSwagger" path="swagger/*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
        <add name="StaticFileModule" path="*.*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>

      <aspNetCore processPath="dotnet" arguments=".\API.dll" hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>