Nswag: Respect LowercaseUrls

Created on 3 Jul 2018  路  18Comments  路  Source: RicoSuter/NSwag

I added the following in my ConfigureServices section.

      services.AddRouting(options =>
      {
        options.LowercaseUrls = true;
      });
      services.AddSwagger();
 app.UseSwaggerUi3WithApiExplorer(settings =>
      {
        settings.GeneratorSettings.DefaultPropertyNameHandling = PropertyNameHandling.Default;
        settings.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("Authorization"));
        settings.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("ServiceAccount"));

        settings.GeneratorSettings.DocumentProcessors.Add(
          new SecurityDefinitionAppender("Authorization", new SwaggerSecurityScheme
          {
            Type = SwaggerSecuritySchemeType.ApiKey,
            Name = "Authorization",
            Description = "The identity token responsible for request.",
            In = SwaggerSecurityApiKeyLocation.Header
          }));

        settings.GeneratorSettings.DocumentProcessors.Add(
          new SecurityDefinitionAppender("ServiceAccount", new SwaggerSecurityScheme
          {
            Type = SwaggerSecuritySchemeType.ApiKey,
            Name = "ServiceAccount",
            Description = "The service account token responsible for request.",
            In = SwaggerSecurityApiKeyLocation.Header
          }));
      });

The capitalization is not being respected in the SwaggerUI.

Similar to https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/74 on Swashbuckle Implementation.

NSwag.AspNetCore on-hold

Most helpful comment

Filed https://github.com/aspnet/Mvc/issues/8006 to track addressing this in MVC.

All 18 comments

It seems that ASP.NET Core API Explorer does not take this into account. Either we implement this on our side, or it has to be fixed in ASP.NET Core API Explorer. @pranavkm Is this by design or a "bug" in ASP.NET Core?

I created a PR to reproduce this: https://github.com/RSuter/NSwag/pull/1433

And indeed the path has still upper case chars:
image

For now, you could implement a document processor which lower cases all paths (except the route param placeholders!).

Hi @RSuter , I made something like this but I don't think this one is heading in the right direction.

Could you provide some tips?

```c#
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NSwag.SwaggerGeneration.Processors;
using NSwag.SwaggerGeneration.Processors.Contexts;

namespace Gapp.Api.Swagger.DocumentProcessors
{
public class ForceLowerCaseRoutes : IDocumentProcessor
{
private readonly ILogger _logger;

public ForceLowerCaseRoutes(ILogger logger)
{
  _logger = logger;
}

public Task ProcessAsync(DocumentProcessorContext context)
{
  var paths = context.Document.Paths.ToDictionary(path => LowerCasePathOnly(path.Key), path => path.Value);
  context.Document.Paths.Clear();
  foreach (var path in paths)
  {
    context.Document.Paths.Add(path);
  }
  return null;
}

private static string LowerCasePathOnly(string path)
{
  StringBuilder result = new StringBuilder();
  bool inScope = false;

  foreach (var c in path)
  {
    char d = ' ';

    switch (c)
    {
      case '{':
        inScope = true;
        break;
      case '}':
        inScope = false;
        break;
    }

    d = !inScope ? char.ToLower(c) : c;

    result.Append(d);
  }
  return result.ToString();
}

}
}
```

image

You can directly call the swagger.json url to see an exception...

But I think it's your return null; in ProcessAsync - it has to return a task instance - use return Task.CompletedTask;

Awesome!!!

To be honest I didn't have any clue about Task.CompletedTask;. I will do some testing. But so far this one works.

```c#
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NSwag.SwaggerGeneration.Processors;
using NSwag.SwaggerGeneration.Processors.Contexts;

namespace Gapp.Api.Swagger.DocumentProcessors
{
public class ForceLowerCaseRoutes : IDocumentProcessor
{
public ForceLowerCaseRoutes()
{
}

public Task ProcessAsync(DocumentProcessorContext context)
{
  var paths = context.Document.Paths.ToDictionary(path => LowerCasePathOnly(path.Key), path => path.Value);
  context.Document.Paths.Clear();
  foreach (var path in paths)
  {
    context.Document.Paths.Add(path);
  }
  return Task.CompletedTask;
}

private static string LowerCasePathOnly(string path)
{
  StringBuilder result = new StringBuilder();
  bool inScope = false;

  foreach (var c in path)
  {
    char d = ' ';

    switch (c)
    {
      case '{':
        inScope = true;
        break;
      case '}':
        inScope = false;
        break;
    }

    d = !inScope ? char.ToLower(c) : c;

    result.Append(d);
  }
  return result.ToString();
}

}
}
```

Good to hear, but I still think that this should be automatically handled by ASP.NET Core API Explorer or at least NSwag :)

BTW: Newer return null as Task, when someone awaits null you'll get a null pointer exception

cc @rynowak @kichalla, do you know off hand if this is something we could handle in ApiExplorer i.e. have LowercaseUrls affect the value in ApiDescription. Is that property only considered during link generation?

Is that property only considered during link generation?

Yes

do you know off hand if this is something we could handle in ApiExplorer i.e. have LowercaseUrls affect the value in ApiDescription

No idea

Filed https://github.com/aspnet/Mvc/issues/8006 to track addressing this in MVC.

Thanks for creating a new issue.

@bangonkali it seems that this is currently not supported by ASP.NET Core API Explorer. I'd suggest to use your document processor for now...

Maybe we can move this processor to the NSwag library so that everyone can use it (not registered by default)?

@RSuter yep we can. I鈥檇 be glad to help. Just guide me if there鈥檚 anything I have to do.

This has been fixed in ASP.NET Core: https://github.com/aspnet/Mvc/issues/8006

Can we close this now?

The fix has been merged indeed by the ASP .NET Core team.
Nevertheless, one could argue that this issue should stay opened until it cannot be reproduced? i.e. ASP .NET Core 2.2 is released

We will try to update our stack to 2.2 and will get back to this. Thanks guys!

Until v2.2 is released you can use the processor above..

Currently using services.AddRouting(options => { options.LowercaseUrls = true; }); on 2.2 but still the generated routes are CamelCase.

c# ... [Produces("application/json")] [Route("api/[controller]")] public class StoresController : ControllerBase ...

image

Okay it turns out I was using

opt.EnableEndpointRouting = false;

If this is false then it will not work. My First use of OData required me to use this but a video from here shows it isn't needed so I've removed it since and the correct casing is now followed.

I think this can now be closed if opt.EnableEndpointRouting = false; is a known side effect.

Was this page helpful?
0 / 5 - 0 ratings