RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.7k stars 1.24k forks source link

Swagger generation from controller for /path/{*param} generates param as a query param #831

Open paulomorgado opened 7 years ago

paulomorgado commented 7 years ago

Given this controller action:

[Route("path/{*param}")

generates the parameter param as in:query, whereas this controller action:

[Route("path/{param}")

generates the parameter param as in:path.

RicoSuter commented 7 years ago

What is the expected behavior of {*param}?

paulomorgado commented 7 years ago

It should by in:path. Shouldn't it?

At least, that's how the client generator interprets it.

RicoSuter commented 7 years ago

The question is how does web api/asp.net core interpret it?

paulomorgado commented 7 years ago

ASP.NET interprets it as in:path. I would expect ASP.NET core to do the same.

NSwag generated clients from swagger definitions in the form of path/{*param} also treat it as in:path.

paulomorgado commented 7 years ago

Sorry for not testing before, but, for this path:

/Inbound/{uid}/{*topic}

The generated C# client has this:

var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("Inbound/{uid}/{*topic}");
urlBuilder_.Replace("{uid}", System.Uri.EscapeDataString(System.Convert.ToString(uid, System.Globalization.CultureInfo.InvariantCulture)));
urlBuilder_.Replace("{topic}", System.Uri.EscapeDataString(System.Convert.ToString(topic, System.Globalization.CultureInfo.InvariantCulture)));

where it should be

var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append("Inbound/{uid}/{*topic}");
urlBuilder_.Replace("{uid}", System.Uri.EscapeDataString(System.Convert.ToString(uid, System.Globalization.CultureInfo.InvariantCulture)));
urlBuilder_.Replace("{*topic}", System.Uri.EscapeDataString(System.Convert.ToString(topic, System.Globalization.CultureInfo.InvariantCulture)));

The * is missing in the URL replacement pattern.

paulomorgado commented 7 years ago

I need to have a better look at this. Probably will take some spec reading.

This way is also escaping the / on topic and that's not what I'm expecting/needing.

If my route is:

[RoutePrefix("path1/path2")]
[Route("path3/{id}/{*topic}")]

This URL:

http://host:port/path1/path2/path3/id/my/special/topic

will yield a value of my/special/topic for topic.

So, when there's an *, there seems to be no path escaping involved.

RicoSuter commented 7 years ago

I think we have to remove the wildcard as swagger does not support it i believe. The problem is how we could detect if escaping is needed or not... I think we should just remove the wildcard in the spec and not escape any path param....

RicoSuter commented 7 years ago

See

RicoSuter commented 7 years ago

For now, we have to treat them as normal string path parameters... The problem is, that path parameters are escaped in the client - so you cannot pass /s... Any idea how to fix that? Maybe we add a custom field? E.g. "x-wildcard": true (which does not render System.Uri.EscapeDataString( in the client?

paulomorgado commented 7 years ago

What do we do with the *? Just not support it?

RicoSuter commented 7 years ago

... see my updated comment above. Not really an ideal solution.

paulomorgado commented 7 years ago

So, in my example, the parameter would be called topic although the path is path1/path2/path3/{id}/{*topic}?

*topic is not a valid C# or TypeScript identifier.

RicoSuter commented 7 years ago

For now, the * is just ignored/removed... Any idea how we should supported that even if Swagger is missing this feature?

paulomorgado commented 7 years ago

What makes sense is for the wildcard only be allowed on the last path parameter and to just not escape it.

I'm using an API Manager (http://wso2.com/products/api-manager) where this route/resource is defined as path1/path2/path3/{id}/* and, in this case, I would like to have a parameter generated for that too.

A143730 commented 3 years ago

hey @paulomorgado - did you get any resolution for this issue, i am also facing the same where the apim path expects / while in .net core the route is /{path} where path includes slashes as well

paulomorgado commented 3 years ago

Sorry, haven't worked with this for about 2 years.