Skip to content

Wrong route variable replacing + language questions #419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
LbISS opened this issue Dec 23, 2018 · 6 comments
Closed

Wrong route variable replacing + language questions #419

LbISS opened this issue Dec 23, 2018 · 6 comments

Comments

@LbISS
Copy link

LbISS commented Dec 23, 2018

Hi, guys.

I'm moving from SDammann.Versioning lib to this project and the process of configuration is better and running more smoothly. Thanks contributors for a great work. As for API itself all is working great, but i have two questions while trying configure the swagger/swashbuckle.

I have removed all conventional routing and left only attribute based one. Currently my route prefix for controllers looks like {language:regex(ru|en|es)}/api/v{version:apiVersion}
I'm configuring my app with the following code:

public class Config
{
	/// <summary>
	/// The route prefix
	/// </summary>
	public const string RoutePrefix = @"{language:regex(ru|en|es)}/api/v{version:apiVersion}/";
	
	/// <summary>
	/// Registers API settings in the specified configuration.
	/// </summary>
	/// <param name="config">The configuration.</param>
	/// <param name="container">The container.</param>
	public static void Register(HttpConfiguration config, IContainer container)
	{
		...
	
		var constraintResolver = new DefaultInlineConstraintResolver()
		{
			ConstraintMap =
			{
				["apiVersion"] = typeof( ApiVersionRouteConstraint )
			}
		};
	
		// Attribute routing.
		config.MapHttpAttributeRoutes(constraintResolver);
	
		config.AddApiVersioning();
	
		//Swagger
		var apiExplorer = config.AddVersionedApiExplorer(
				options =>
				{
					options.GroupNameFormat = "'v'VVV";
					options.SubstituteApiVersionInUrl = true;
				});

		config
			.EnableSwagger("{apiVersion}/swagger", 
				c =>
				{
					c.MultipleApiVersions(
						(apiDescription, version) => apiDescription.GetGroupName() == version,
						info =>
						{
							foreach (var group in apiExplorer.ApiDescriptions)
							{
								var description = "";
								if (group.IsDeprecated)
								{
									description += "This API version has been deprecated.";
								}

								info.Version(group.Name, $"Restaurants API {group.ApiVersion}")
									.Description(description);
							}
						});
	
					...
	
					c.OperationFilter<SwaggerAuthOperationFilter>(); 
					c.OperationFilter<SwaggerDefaultFilter>();

					...

					c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
				})
			.EnableSwaggerUi(c =>
				{
					c.EnableDiscoveryUrlSelector();
				});
	}
}

And i have the next controller:

[RoutePrefix(Config.RoutePrefix + "test")]
[ApiVersion("1.0")]
[ApiVersion("1.1")]
[ApiVersion("2.0")]
...
public class TestController : BaseController
{
	/// <summary>
	/// Used to check if server alive.
	/// </summary>
	/// <returns>Time and version of server</returns>
	[HttpGet]
	[Route("")]
	[ResponseType(typeof(TestResult))]
	public IHttpActionResult Get()
	{
		
		return Ok(new TestResult
		{
			Result = @"Success",
			ServerDateTime = DateTimeOffset.Now,
			Build = GetExecutingAssemblyModifiedDate().ToString("yyyy.MM.dd HH:mm")
		});
	}
}

After running app and opening swagger i'm seeing the next route:
s1

  1. Why {language} tag have been replaced with version instead of {version} tag? How can i prevent this behaviour?
  2. If i'll hardcode "en" for {language} param:
    RoutePrefix = "en/api/v{version:apiVersion}/"
    then the version tag is substituting for v1. But request from swagger not working nevertheless - it's going on "en/api/v1/test", but the application returns 406.0 - Not Acceptable, it's awaiting request on "en/api/v1.0/test". How can setup swagger correctly?

I have ASP.Net WebAPI 2 project (.net 4.7.2.) with Swashbuckle 5.6.0 & Microsoft.AspNet.WebApi.Versioning.ApiExplorer 3.0.0

I've found this issue: #113, but for now i can't use approach with headers due to neccessity of backward compatibility.

I'll appreciate any help.

@commonsensesoftware commonsensesoftware self-assigned this Dec 23, 2018
@LbISS
Copy link
Author

LbISS commented Dec 23, 2018

I'm sorry, i've found mistake in IIS rewrite rules (406 gave me a hint), so the second question is solved - routes with v1 corrrectly resolving. But i'm still have problem with language tag.

@commonsensesoftware
Copy link
Collaborator

There are two issues here; one causing the other. Ultimately, this is happening because you are missing the language parameter in your controller action. The signature should be:

[HttpGet]
[Route]
[ResponseType(typeof(TestResult))]
public IHttpActionResult Get(string language) { /* omitted */ }

In addition, the logic to generate the API parameter description for an API version in the path looks for an existing partial parameter description. The parameter description is always consistently missing some information because the API version is usually not model bound. Because the language parameter is also not model bound (to an action parameter), it is being incorrectly identified as the API version parameter.

This shouldn't be a landmine that's so easy to step on. After a quick investigation, it's possible to make the API Explorer logic more reliable to avoid this type of situation. I'll put out a patch when I can. In the meantime, simply update your action definition and you should be on your way.

@LbISS
Copy link
Author

LbISS commented Dec 23, 2018

Thanks for response!
For now language parameter handled for all controllers in one handler, not in actions themselves. It'll be rather time-consuming to add parameter in each action.
May be there are any another workarounds, something like changing ApiExplorer.ApiDescriptions?

commonsensesoftware pushed a commit that referenced this issue Dec 23, 2018
@commonsensesoftware
Copy link
Collaborator

I see. I thought you might have been able to work around this issue without an update, but it seems not. I've published the fix in 3.0.1 of the API Explorer. Indexing and such on the NuGet site isn't done yet, so might have to explicitly update the version or restore by command line. This version should appear in searches within the next 15 minutes.

I was able to repro your scenario, so I expect this change to resolve the issue for you. Let me know one way or the other. Thanks.

@LbISS
Copy link
Author

LbISS commented Dec 24, 2018

Thanks! It works perfectly!

@commonsensesoftware
Copy link
Collaborator

Seems like this issue is resolved now. Feel free to come back if you have more questions or issues. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants