public void add_parameter_should_add_descriptor_for_query_parameter() { // arrange var version = new ApiVersion(1, 0); var description = NewApiDescription(version); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))).Object; var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = new QueryStringApiVersionReader() }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata, options); // act context.AddParameter("api-version", Query); // assert description.ParameterDescriptions.Single().Should().BeEquivalentTo( new { Name = "api-version", ModelMetadata = modelMetadata, Source = BindingSource.Query, DefaultValue = (object)"1.0", IsRequired = true, Type = typeof(string), }, o => o.ExcludingMissingMembers()); }
public void add_parameter_should_add_descriptor_for_header() { // arrange var version = new ApiVersion(1, 0); var description = NewApiDescription(version); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))); var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = new HeaderApiVersionReader() }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata.Object, options); // act context.AddParameter("api-version", Header); // assert description.ParameterDescriptions.Single().Should().BeEquivalentTo( new { Name = "api-version", ModelMetadata = modelMetadata, Source = BindingSource.Header, RouteInfo = new ApiParameterRouteInfo() { DefaultValue = "1.0", IsOptional = false }, Type = typeof(string) }, o => o.ExcludingMissingMembers()); }
public void add_parameter_should_add_optional_parameter_when_allowed() { // arrange var version = new ApiVersion(1, 0); var description = NewApiDescription(version); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))); var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = new QueryStringApiVersionReader(), AssumeDefaultVersionWhenUnspecified = true }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata.Object, options); // act context.AddParameter("api-version", Query); // assert description.ParameterDescriptions.Single().Should().BeEquivalentTo( new { Name = "api-version", ModelMetadata = modelMetadata, Source = BindingSource.Query, RouteInfo = new ApiParameterRouteInfo() { DefaultValue = "1.0", IsOptional = true }, Type = typeof(string) }, o => o.ExcludingMissingMembers()); }
public void add_parameter_should_not_add_query_parameter_after_path_parameter_has_been_added() { // arrange var parameter = new ApiParameterDescription() { Name = "api-version", RouteInfo = new ApiParameterRouteInfo() { Constraints = new IRouteConstraint[] { new ApiVersionRouteConstraint() } }, Source = BindingSource.Path }; var version = new ApiVersion(1, 0); var description = NewApiDescription(version, parameter); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))); var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = Combine(new QueryStringApiVersionReader(), new UrlSegmentApiVersionReader()) }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata.Object, options); modelMetadata.SetupGet(m => m.DataTypeName).Returns(nameof(ApiVersion)); // act context.AddParameter("api-version", Path); context.AddParameter("api-version", Query); // assert description.ParameterDescriptions.Should().HaveCount(1); }
public void add_parameter_should_remove_other_descriptors_after_path_parameter_is_added() { // arrange var parameter = new ApiParameterDescription() { Name = "api-version", RouteInfo = new ApiParameterRouteInfo() { Constraints = new IRouteConstraint[] { new ApiVersionRouteConstraint() } }, Source = BindingSource.Path }; var description = new ApiDescription() { ParameterDescriptions = { parameter } }; var version = new ApiVersion(1, 0); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))); var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = Combine(new QueryStringApiVersionReader(), new UrlSegmentApiVersionReader()) }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata.Object, options); modelMetadata.SetupGet(m => m.DataTypeName).Returns(nameof(ApiVersion)); // act context.AddParameter("api-version", Query); context.AddParameter("api-version", Path); // assert description.ParameterDescriptions.Single().ShouldBeEquivalentTo( new { Name = "api-version", ModelMetadata = modelMetadata, Source = BindingSource.Path, RouteInfo = new ApiParameterRouteInfo() { DefaultValue = "1.0", IsOptional = false, Constraints = parameter.RouteInfo.Constraints }, Type = typeof(string) }, o => o.ExcludingMissingMembers()); }
public void add_parameter_should_add_descriptor_for_media_type_parameter() { // arrange const string Json = "application/json"; var version = new ApiVersion(1, 0); var description = new ApiDescription() { ActionDescriptor = new ActionDescriptor() { Properties = { [typeof(ApiVersionModel)] = new ApiVersionModel(version) } }, SupportedRequestFormats = { new ApiRequestFormat() { MediaType = Json } }, SupportedResponseTypes = { new ApiResponseType() { ApiResponseFormats = { new ApiResponseFormat() { MediaType = Json } } } } }; var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))); var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = new MediaTypeApiVersionReader() }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata.Object, options); // act context.AddParameter("v", MediaTypeParameter); // assert description.SupportedRequestFormats.Single().MediaType.Should().Be("application/json; v=1.0"); description.SupportedResponseTypes.Single().ApiResponseFormats.Single().MediaType.Should().Be("application/json; v=1.0"); }
public ApiVersionParameterDescriptionContext( ApiDescription apiDescription, ApiVersion apiVersion, ModelMetadata modelMetadata, ApiExplorerOptions options) { Arg.NotNull(apiDescription, nameof(apiDescription)); Arg.NotNull(apiVersion, nameof(apiVersion)); Arg.NotNull(modelMetadata, nameof(modelMetadata)); Arg.NotNull(options, nameof(options)); ApiDescription = apiDescription; ApiVersion = apiVersion; ModelMetadata = modelMetadata; Options = options; optional = options.AssumeDefaultVersionWhenUnspecified && apiVersion == options.DefaultApiVersion; }
public ApiVersionParameterDescriptionContext( ApiDescription apiDescription, ApiVersion apiVersion, ModelMetadata modelMetadata, ApiExplorerOptions options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } ApiDescription = apiDescription; ApiVersion = apiVersion; ModelMetadata = modelMetadata; Options = options; optional = options.AssumeDefaultVersionWhenUnspecified && apiVersion == options.DefaultApiVersion; versionNeutral = new Lazy <bool>(() => ApiDescription.ActionDescriptor.GetApiVersionModel().IsApiVersionNeutral); }
public ApiVersionParameterDescriptionContext( ApiDescription apiDescription, ApiVersion apiVersion, ModelMetadata modelMetadata, ApiExplorerOptions options) { Arg.NotNull(apiDescription, nameof(apiDescription)); Arg.NotNull(apiVersion, nameof(apiVersion)); Arg.NotNull(modelMetadata, nameof(modelMetadata)); Arg.NotNull(options, nameof(options)); ApiDescription = apiDescription; ApiVersion = apiVersion; ModelMetadata = modelMetadata; Options = options; optional = options.AssumeDefaultVersionWhenUnspecified && apiVersion == options.DefaultApiVersion; versionNeutral = new Lazy <bool>(() => ApiDescription.ActionDescriptor.GetApiVersionModel().IsApiVersionNeutral); }
public void add_parameter_should_add_descriptor_for_path() { // arrange var parameter = new ApiParameterDescription() { Name = "api-version", RouteInfo = new ApiParameterRouteInfo() { Constraints = new IRouteConstraint[] { new ApiVersionRouteConstraint() } }, Source = BindingSource.Path }; var version = new ApiVersion(1, 0); var description = NewApiDescription(version, parameter); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))).Object; var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = new UrlSegmentApiVersionReader() }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata, options); // act context.AddParameter("api-version", Path); // assert description.ParameterDescriptions.Single().Should().BeEquivalentTo( new { Name = "api-version", ModelMetadata = modelMetadata, Source = BindingSource.Path, DefaultValue = (object)"1.0", IsRequired = true, RouteInfo = new ApiParameterRouteInfo() { DefaultValue = "1.0", IsOptional = false, Constraints = parameter.RouteInfo.Constraints, }, Type = typeof(string), }, o => o.ExcludingMissingMembers()); }
public void add_parameter_should_make_parameters_optional_after_first_parameter() { // arrange var version = new ApiVersion(1, 0); var description = NewApiDescription(version); var modelMetadata = new Mock <ModelMetadata>(ModelMetadataIdentity.ForType(typeof(string))); var options = new ApiExplorerOptions() { DefaultApiVersion = version, ApiVersionParameterSource = Combine(new QueryStringApiVersionReader(), new HeaderApiVersionReader()) }; var context = new ApiVersionParameterDescriptionContext(description, version, modelMetadata.Object, options); // act context.AddParameter("api-version", Query); context.AddParameter("api-version", Header); // assert description.ParameterDescriptions[0].RouteInfo.IsOptional.Should().BeFalse(); description.ParameterDescriptions[1].RouteInfo.IsOptional.Should().BeTrue(); }
/// <summary> /// Attempts to update the relate path of the specified API description and remove the corresponding parameter according to the specified options. /// </summary> /// <param name="apiDescription">The <see cref="ApiDescription">API description</see> to attempt to update.</param> /// <param name="options">The current <see cref="ApiExplorerOptions">API Explorer options</see>.</param> /// <returns>True if the <paramref name="apiDescription">API description</paramref> was updated; otherwise, false.</returns> public static bool TryUpdateRelativePathAndRemoveApiVersionParameter(this ApiDescription apiDescription, ApiExplorerOptions options) { Arg.NotNull(apiDescription, nameof(apiDescription)); Arg.NotNull(options, nameof(options)); if (!options.SubstituteApiVersionInUrl) { return(false); } var parameter = apiDescription.ParameterDescriptions.FirstOrDefault(pd => pd.Source == Path && pd.ModelMetadata?.DataTypeName == nameof(ApiVersion)); if (parameter == null) { return(false); } var relativePath = apiDescription.RelativePath; var token = '{' + parameter.Name + '}'; var value = apiDescription.GetApiVersion().ToString(options.SubstitutionFormat, InvariantCulture); var newRelativePath = relativePath.Replace(token, value); if (relativePath == newRelativePath) { return(false); } apiDescription.RelativePath = newRelativePath; apiDescription.ParameterDescriptions.Remove(parameter); return(true); }
/// <summary> /// Attempts to update the relate path of the specified API description and remove the corresponding parameter according to the specified options. /// </summary> /// <param name="apiDescription">The <see cref="ApiDescription">API description</see> to attempt to update.</param> /// <param name="options">The current <see cref="ApiExplorerOptions">API Explorer options</see>.</param> /// <returns>True if the <paramref name="apiDescription">API description</paramref> was updated; otherwise, false.</returns> public static bool TryUpdateRelativePathAndRemoveApiVersionParameter(this ApiDescription apiDescription, ApiExplorerOptions options) { if (apiDescription == null) { throw new ArgumentNullException(nameof(apiDescription)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } if (!options.SubstituteApiVersionInUrl) { return(false); } var parameter = apiDescription.ParameterDescriptions.FirstOrDefault(pd => pd.Source == Path && pd.ModelMetadata?.DataTypeName == nameof(ApiVersion)); if (parameter == null) { return(false); } var relativePath = apiDescription.RelativePath; var token = '{' + parameter.Name + '}'; var value = apiDescription.GetApiVersion().ToString(options.SubstitutionFormat, InvariantCulture); #if NETSTANDARD2_0 var newRelativePath = relativePath.Replace(token, value); #else var newRelativePath = relativePath.Replace(token, value, StringComparison.Ordinal); #endif if (relativePath == newRelativePath) { return(false); } apiDescription.RelativePath = newRelativePath; apiDescription.ParameterDescriptions.Remove(parameter); return(true); }
public void versioned_api_explorer_should_group_and_order_descriptions_on_providers_executed() { // arrange var actionProvider = new TestActionDescriptorCollectionProvider(); var context = new ApiDescriptionProviderContext(actionProvider.ActionDescriptors.Items); var modelMetadataProvider = NewModelMetadataProvider(); var apiExplorerOptions = new ApiExplorerOptions() { GroupNameFormat = "'v'VVV" }; var apiExplorer = new VersionedApiDescriptionProvider(modelMetadataProvider, Options.Create(apiExplorerOptions)); foreach (var action in context.Actions) { context.Results.Add(new ApiDescription() { ActionDescriptor = action }); } // act apiExplorer.OnProvidersExecuted(context); // assert context.Results.Should().BeEquivalentTo( new[] { // orders new { GroupName = "v0.9", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(0, 9) } }, new { GroupName = "v1", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(1, 0) } }, new { GroupName = "v1", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(1, 0) } }, new { GroupName = "v2", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(2, 0) } }, new { GroupName = "v2", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(2, 0) } }, new { GroupName = "v2", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(2, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, // people new { GroupName = "v0.9", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(0, 9) } }, new { GroupName = "v1", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(1, 0) } }, new { GroupName = "v1", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(1, 0) } }, new { GroupName = "v2", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(2, 0) } }, new { GroupName = "v2", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(2, 0) } }, new { GroupName = "v2", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(2, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, new { GroupName = "v3", Properties = new Dictionary <object, object>() { [typeof(ApiVersion)] = new ApiVersion(3, 0) } }, }, options => options.ExcludingMissingMembers()); }