Swashbuckle.aspnetcore: IIS Deployment does not work with min config on Core V1

Created on 20 Jul 2016  路  4Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

I am not sure if I am doing something wrong, or missing a step somewhere.
I am using ASP.NET Core V1 and Swashbuckle 6.0.0-beta901 with the minimum config from the Readme.

Everything works like a charm in localhost.

When using a filesystem deploy to IIS, Ahoy no longer works fully. The swagger page renders, but it cannot read the json file. It appears that swagger is not respecting the relative pathing, and that the IIS drop folder does not actually contain any of the generated files.

Any ideas? Possible bug?

Most helpful comment

You should take a look at the virtual directory example here https://github.com/domaindrivendev/Ahoy/blob/master/test/WebSites/

By design, the SwaggerGen (generates and serves swagger.json) and the SwaggerUi (embedded html, css, JS) components are fully decoupled. This means you have to tell the latter which URL it should use to obtain a JSON description of the API. By default, this is hardcoded to be "/swagger/v1/swagger.json" which works automagically in many cases but not all - e.g. a different version or, as in your case, when the app is served through a virtual directory.

I know this isn't ideal and am looking into alternatives that don't compromise the decoupling of components which I want to maintain. However, in the meantime, you should be able to resolve this with the following config change in your Startup.cs

if (!_hostingEnv.IsDevelopment())
{
    UseSwaggerUi(swaggerUrl: "/MyApp/swagger/v1/swagger.json");
}

All 4 comments

Same problem here. When I browse to my app (http://localhost/MyApp/swagger/ui/index.html) I get the following error:
Can't read swagger JSON from http://localhost/swagger/v1/swagger.json

But, I can "see" the json when I browse to http://localhost/MyApp/swagger/v1/swagger.json

You should take a look at the virtual directory example here https://github.com/domaindrivendev/Ahoy/blob/master/test/WebSites/

By design, the SwaggerGen (generates and serves swagger.json) and the SwaggerUi (embedded html, css, JS) components are fully decoupled. This means you have to tell the latter which URL it should use to obtain a JSON description of the API. By default, this is hardcoded to be "/swagger/v1/swagger.json" which works automagically in many cases but not all - e.g. a different version or, as in your case, when the app is served through a virtual directory.

I know this isn't ideal and am looking into alternatives that don't compromise the decoupling of components which I want to maintain. However, in the meantime, you should be able to resolve this with the following config change in your Startup.cs

if (!_hostingEnv.IsDevelopment())
{
    UseSwaggerUi(swaggerUrl: "/MyApp/swagger/v1/swagger.json");
}

Adding that line of code to the Configure method of Startup.cs worked for me. Thanks!

@domaindrivendev Thanks, but I am not sure if I am missing something, or there was change/regression.

With the rebranding of your package, the Virtual Directory example you reference is no longer available in master branch. I wasn't sure if this was intended or not, but I was able to find it in a different branch: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/tree/aspnetcore-rename/test/WebSites/VirtualDirectory

When taking that approach, I can get it to work, if I make some sacrifices on route naming. Specifically, either I have to let it be the default /swagger for the ui because I don't set RoutePrefix, or I get an extra subdirectory in the route.

Ideally, I would like to have it set up with this once deployed:
/api/ => the actual api
/api/docs => the swagger ui

Snip:

app.UseMvc();

if (!env.IsDevelopment())
{
    app.Map("/docs", subApp =>
    {
        // Configure the HTTP request pipeline.
        subApp.UseStaticFiles();

        // Add MVC to the request pipeline.
        subApp.UseMvc();

        subApp.UseSwagger();
        subApp.UseSwaggerUi(c =>
        {
            c.RoutePrefix = "docs"; 
            c.SwaggerEndpoint("/api/docs/swagger/Alpha1/swagger.json", "MyCool Alpha1");
        });
    });
}
else
{
    app.UseSwagger();
    app.UseSwaggerUi(c =>
    {
        c.RoutePrefix = "docs"; 
        c.SwaggerEndpoint("/swagger/Alpha1/swagger.json", "MyCool Alpha1");
    });
}

Was this page helpful?
0 / 5 - 0 ratings