After upgrading from 5.13.2 to 6.0.3 swagger-ui is not working

Executing any service via the swagger-ui (openapi) page is responding with a 405 status.

I have noticed that with 6.0.3, the metadata page no longer lists the Swagger UI link under the Plugin Links; it was listed using 5.13.2. The url for the swagger-ui works directly in the browser.

The C# breakpoint on the service is not being reached.

Have I missed something with the upgrade?

(Platform is NET6 on Windows 10.)

For example, for one of my simple GET endpoints:

https://localhost:7560/swagger-ui/#/App/GetUserSettingappusersetting_Get

request:

https://localhost:72560/api/app/usersetting

response: (405)

{
  "responseStatus": {
    "errorCode": "NotImplementedException",
    "message": "The operation 'usersetting' does not exist for this service",
    "stackTrace": null,
    "errors": [],
    "meta": null
  }
}

Executing the same service directly from the new API Explorer works.

https://localhost:72560/ui/GetUserSetting

Also
https://localhost:72560/api/app/usersetting FAILS as above
https://localhost:72560/api/GetUserSetting WORKS

request:

https://localhost:72560/api/GetUserSetting

response:

{
    "offset": 0,
    "total": 0,
    "results": [
        {
            "id": "1",
            "accountId": "1",
            "keyName": "Theme",
            "keyValue": "Light",
            "description": null,
            "rowVersion": 14012
        }
    ],
    "meta": {},
    "responseStatus": null
}

This request looks in conflict with the new pre-defined /api route which should only be used for ServiceStack APIs if enabled.

See this previous answer for how to change and disable the /api pre-defined route:

Thank you for the quick response.

I am still unsure what I need to do. I need ALL my services to have a /api prefix, which I was previously doing with the following in AppHost.cs:

https://docs.servicestack.net/routing#customizing-defined-routes

// Override to use /api prefix on all services

public override RouteAttribute[] GetRouteAttributes(Type requestType)
{
    var routes = base.GetRouteAttributes(requestType);
    routes.Each(x => x.Path = "/api" + x.Path);
    return routes;
}

If I comment out the above code, the swagger-ui is working, but now the url has app and not my required api prefix

https://localhost:72560/app/usersetting

I tried using the following in my AppHost.Configure() method to bring back the /api prefix, but it did not work:.

// Enforce /api prefix on all services
ConfigurePlugin<PredefinedRoutesFeature>(feature =>
    feature.JsonApiRoute = "/api/{Request}");

What do I need to do?

BTW: I added the swagger-ui link back to the metadata page using the documented code in my AppHost.Configure() method:

// Add OpenApiFeature /swagger-ui link to /metadata page
var swaggerUrl = "swagger-ui/";
ConfigurePlugin<MetadataFeature>(
    feature => feature.AddPluginLink(swaggerUrl, "Swagger UI"));

Then I don’t understand the issue, where does /app/usersettings come from?

Sorry, my mistake that it was not clear from my response, app is from my routing:

The services definition is

[Tag("App")]
[ValidateIsAuthenticated]
[ValidateHasRole(UserRole.ReadData)]
[Route("/app/usersetting", "GET")]                         // api prefix not hardcoded
public class GetUserSetting : QueryDb<UserSetting>, IGet
{
    public int? Id { get; init; }
    public int? AccountId { get; init; }
}

Previously, under ServiceStack v5 and the GetRouteAttributes override above, the api prefix was enforced:

https://localhost:72560/api/app/usersetting WORKED

With the commenting out the GetRouteAttributes (described above), the url is without api prefix:

https://localhost:72560/app/usersetting WORKS

So, what I need is to understand how I can restore the /api prefix on all my routes using ServiceStack v6?

We didn’t make any changes here, but dynamically mutating the routes on the server is very fragile where changing the order of execution can cause issues.

The cleanest way is going to be have the route attribute contain the full path, i.e. include the /api prefix so the [Route] contains the true path which other static analyzers & client libraries also have access to.

Can you disable the /api route:

ConfigurePlugin<PredefinedRoutesFeature>(feature => feature.JsonApiRoute = null);

Make sure GetRouteAttributes(Type requestType) is uncommented out and include the raw HTTP Request/Response headers for the previous route that worked.

Following you suggestions: restoring my GetRouteAttributes() code and disabling the /api route with the ConfigurePlugin statement , I now have a working solution:

  • https://localhost:72560/api/app/usersetting WORKS
  • https://localhost:72560/ui/GetUserSetting WORKS
  • https://localhost:72560/json/reply/GetUserSetting WORKS
    ** Before disabling api was https://localhost:72560/api/GetUserSetting

Also:

  • https://localhost:72560/ui/ WORKS
  • https://localhost:72560/swagger-ui WORKS

I think you are correct that the Router attribute should be the truth, so I will refactor to put the /api directly in the endpoint paths and then adjust the configurations.

I do not think they are needed now, but as you asked, please see the request headers with the working changes:

request:
https://localhost:72560/api/app/usersetting

response headers:
access-control-allow-credentials: true
access-control-allow-headers: Content-Type
access-control-allow-methods: GET,POST,PUT,DELETE,PATCH,OPTIONS
access-control-allow-origin: http://localhost:72560
access-control-max-age: 600
content-type: application/json; charset=utf-8
date: Mon,14 Feb 2022 11:39:44 GMT
server: Kestrel
vary: Accept
x-powered-by: ServiceStack/6.03 NET6/Windows/net6/BU

1 Like

Thank you for the great support again.

1 Like