Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

// ReSharper disable once CheckNamespace
namespace Swashbuckle.AspNetCore.Annotations
{
/// <summary>
/// Causes the annotated member to be ignored during schema generation.
/// Does not alter serialization behavior.
/// </summary>
/// <remarks>
/// Can be used in combination with <see cref="System.Text.Json.Serialization.JsonExtensionDataAttribute"/>
/// to capture and invalidate unsupported properties.
/// </remarks>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property)]
public sealed class SwaggerIgnoreAttribute : Attribute { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Swashbuckle.AspNetCore.Annotations;

namespace Swashbuckle.AspNetCore.SwaggerGen
{
Expand Down Expand Up @@ -166,6 +167,7 @@ private IEnumerable<DataProperty> GetDataPropertiesFor(Type objectType, out Type
(property.IsPubliclyReadable() || property.IsPubliclyWritable()) &&
!(property.GetIndexParameters().Any()) &&
!(property.HasAttribute<JsonIgnoreAttribute>() && isIgnoredViaNet5Attribute) &&
!(property.HasAttribute<SwaggerIgnoreAttribute>()) &&
!(_serializerOptions.IgnoreReadOnlyProperties && !property.IsPubliclyWritable());
})
.OrderBy(property => property.DeclaringType.GetInheritanceChain().Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.Swagger;
#if NET7_0_OR_GREATER
using Microsoft.AspNetCore.Http.Metadata;
Expand Down Expand Up @@ -86,6 +87,7 @@ public OpenApiDocument GetSwagger(string documentName, string host = null, strin
var applicableApiDescriptions = _apiDescriptionsProvider.ApiDescriptionGroups.Items
.SelectMany(group => group.Items)
.Where(apiDesc => !(_options.IgnoreObsoleteActions && apiDesc.CustomAttributes().OfType<ObsoleteAttribute>().Any()))
.Where(apiDesc => !apiDesc.CustomAttributes().OfType<SwaggerIgnoreAttribute>().Any())
.Where(apiDesc => _options.DocInclusionPredicate(documentName, apiDesc));

var schemaRepository = new SchemaRepository(documentName);
Expand Down Expand Up @@ -319,6 +321,7 @@ private IList<OpenApiParameter> GenerateParameters(ApiDescription apiDescription
{
return (!apiParam.IsFromBody() && !apiParam.IsFromForm())
&& (!apiParam.CustomAttributes().OfType<BindNeverAttribute>().Any())
&& (!apiParam.CustomAttributes().OfType<SwaggerIgnoreAttribute>().Any())
&& (apiParam.ModelMetadata == null || apiParam.ModelMetadata.IsBindingAllowed);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Swashbuckle.AspNetCore.Annotations;

namespace Swashbuckle.AspNetCore.SwaggerGen.Test
{
Expand Down Expand Up @@ -49,6 +50,9 @@ public void ActionWithIntParameterWithDefaultValueAttribute([DefaultValue(3)]int
public void ActionWithIntParameterWithRequiredAttribute([Required]int param)
{ }

public void ActionWithIntParameterWithSwaggerIgnoreAttribute([SwaggerIgnore] int param)
{ }

public void ActionWithObjectParameter(XmlAnnotatedType param)
{ }

Expand Down Expand Up @@ -76,5 +80,9 @@ public int ActionWithProducesAttribute()
{
throw new NotImplementedException();
}

[SwaggerIgnore]
public void ActionWithSwaggerIgnoreAttribute()
{ }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using Swashbuckle.AspNetCore.Annotations;

namespace Swashbuckle.AspNetCore.SwaggerGen.Test.Fixtures
{
public class SwaggerIngoreAnnotatedType
{
public string NotIgnoredString { get; set; }

[SwaggerIgnore]
public string IgnoredString { get; set; }

[SwaggerIgnore]
[JsonExtensionData]
public IDictionary<string, JsonElement> IgnoredExtensionData { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.TestSupport;
using Swashbuckle.AspNetCore.SwaggerGen.Test.Fixtures;
using Xunit;

namespace Swashbuckle.AspNetCore.SwaggerGen.Test
Expand Down Expand Up @@ -824,6 +825,22 @@ public void GenerateSchema_HonorsSerializerAttribute_JsonExtensionData()
Assert.Null(schema.AdditionalProperties.Type);
}

[Fact]
public void GenerateSchema_HonorsAttribute_SwaggerIgnore()
{
var schemaRepository = new SchemaRepository();

var referenceSchema = Subject().GenerateSchema(typeof(SwaggerIngoreAnnotatedType), schemaRepository);

var schema = schemaRepository.Schemas[referenceSchema.Reference.Id];

Assert.True(schema.Properties.ContainsKey(nameof(SwaggerIngoreAnnotatedType.NotIgnoredString)));
Assert.False(schema.Properties.ContainsKey(nameof(SwaggerIngoreAnnotatedType.IgnoredString)));
Assert.False(schema.Properties.ContainsKey(nameof(SwaggerIngoreAnnotatedType.IgnoredExtensionData)));
Assert.False(schema.AdditionalPropertiesAllowed);
Assert.Null(schema.AdditionalProperties);
}

[Theory]
[InlineData(typeof(object))]
[InlineData(typeof(JsonDocument))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,27 @@ public void GetSwagger_GeneratesParameters_ForApiParametersThatAreNotBoundToBody
Assert.Equal(expectedParameterLocation, parameter.In);
}

[Fact]
public void GetSwagger_IgnoresOperations_IfOperationHasSwaggerIgnoreAttribute()
{
var subject = Subject(
apiDescriptions: new[]
{
ApiDescriptionFactory.Create<FakeController>(
c => nameof(c.ActionWithSwaggerIgnoreAttribute),
groupName: "v1",
httpMethod: "POST",
relativePath: "ignored",
parameterDescriptions: Array.Empty<ApiParameterDescription>()
)
}
);

var document = subject.GetSwagger("v1");

Assert.Empty(document.Paths);
}

[Fact]
public void GetSwagger_IgnoresParameters_IfActionParameterHasBindNeverAttribute()
{
Expand Down Expand Up @@ -452,6 +473,35 @@ public void GetSwagger_IgnoresParameters_IfActionParameterHasBindNeverAttribute(
Assert.Empty(operation.Parameters);
}

[Fact]
public void GetSwagger_IgnoresParameters_IfActionParameterHasSwaggerIgnoreAttribute()
{
var subject = Subject(
new[]
{
ApiDescriptionFactory.Create<FakeController>(
c => nameof(c.ActionWithIntParameterWithSwaggerIgnoreAttribute),
groupName: "v1",
httpMethod: "POST",
relativePath: "resource",
parameterDescriptions: new[]
{
new ApiParameterDescription
{
Name = "param",
Source = BindingSource.Query
}
}
)
}
);

var document = subject.GetSwagger("v1");

var operation = document.Paths["/resource"].Operations[OperationType.Post];
Assert.Empty(operation.Parameters);
}

[Fact]
public void GetSwagger_SetsParameterRequired_IfApiParameterIsBoundToPath()
{
Expand Down