Closed KillerBoogie closed 3 days ago
Swashbuckle.AspNetCore 6.5.0 Swashbuckle.AspNetCore.Annotations 6.5.0. .Net 7
I reviewed AnnotationsSchemaFilter in Swashbuckle.AspNetCore.Annotations
I can not find any places remove property from schema (schema.Properties.Remove(excludedName))
I created another filter and use SwaggerSchemaAttribute in Swashbuckle.AspNetCore.Annotations
public class SwaggerIgnoreFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (schema?.Properties == null)
{
return;
}
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var memberList = context.Type
.GetFields(bindingFlags).Cast<MemberInfo>()
.Concat(context.Type.GetProperties(bindingFlags));
var excludedList = memberList
.Where(m => m.GetCustomAttribute<SwaggerSchemaAttribute>() != null)
.Select(m => m.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName ?? m.Name.ToCamelCase());
foreach (var excludedName in excludedList)
{
if (schema.Properties.ContainsKey(excludedName))
schema.Properties.Remove(excludedName);
}
}
}
public static class StringExtension
{
public static string ToCamelCase(this string str)
{
if (!string.IsNullOrEmpty(str) && str.Length > 1)
{
return char.ToLowerInvariant(str[0]) + str.Substring(1);
}
return str.ToLowerInvariant();
}
}
and program.cs add following
builder.Services.AddSwaggerGen(options =>
{
options.SchemaFilter<SwaggerIgnoreFilter>();
}
It is working perfect
Is SwaggerSchemaAttribute respected while genration open API spec in minimal APIs?
any updates?
Attempt 1: [FromServices]
[FromServices] parameters are not shown in DotSwashbuckle, can you test if that solves your problem?
I am also having this problem
You can try putting [BindNever] attribute over the property you don't want to be shown in swagger ui, as suggested in this comment. However this attribute might only work with [FromQuery], I've seen some discussion why its not working with [FromBody].
This issue is stale because it has been open for 60 days with no activity. It will be automatically closed in 14 days if no further updates are made.
@KillerBoogie, with the last version of Swashbuckle, there's a attribute that is SwagerIgnore, that would do the trick. However as I have seen you are trying to do not show some parameters of the body, in case the parameters are meant to be hidden but accesible you can put the SwaggerIgnore in the properties of the body.
But if you do not want to deserialize those properties at all the JsonIgnore is your way to go.
Also mention the BindNever attribute for properties that are not in the body
Thanks for the information! I have been off the project for a while. I can check it next week.
I found that to get [SwaggerSchema(ReadOnly = true)] to work, you have to enable swagger annotations elsewhere in your project.
For my project, that was within Program.cs like this:
builder.Services.AddSwaggerGen(c =>
{
c.EnableAnnotations(); // Enable annotations in Swagger
});
After that, the ReadOnly annotation worked as I expected.
This issue is stale because it has been open for 60 days with no activity. It will be automatically closed in 14 days if no further updates are made.
This issue was closed because it has been inactive for 14 days since being marked as stale.
Swashbuckle.AspNetCore 6.5.0 Swashbuckle.AspNetCore.Annotations 6.5.0. .Net 7
Goal
I was trying to model bind multiple sources to a single class and ignore some parameters with
[SwaggerSchema(ReadOnly = true)]
. I thought that this is a common scenario. E.g. environment parameters that are collected fromHttpContext
must not show as input parameters in Swagger UI. They don't come from request parameters and will be bound by a custom model binder.Model binding to class doesn't work
I first had to realize that the basic binding doesn't work as it is documented at Microsoft Learn: Model Binding in ASP.NET Core. Currently, it seems that model binding to a single flat class does not work. I created an issue (https://github.com/dotnet/AspNetCore.Docs/issues/29295).
Partial Workaround
The only working options that I found is to have a sub class for the body as a parameter and either set the following option
or from .Net 6 on, mark the single class with `[FromQuery]' (which is not intuitive). This is not documented and it took me two days of frustration to find it in a comment of a post.
After this issue has a workaround I can continue to the main topic of this post: hide parameters from Swagger UI.
Attempt 1: [FromServices]
My first natural seeming attempt was to annotate the properties to be hidden with
[FromServices]
.It worked partly. Properties from
TestDetails
are hidden in Swagger UI, but not the property in theArtist
class. The properties are also not hidden from the models that are displayed below the endpoints in Swagger UI.A partial workaround is to use two classes as parameters. One for the body parameters and one for the others (query, header, modelbinded, etc.).
RequestDetails
does not show up in the model list. But again[FromServices]
does not work to hide a body property.Attempt 2: [SwaggerSchema(ReadOnly = true)]
I then found the annotation package and the '[SwaggerSchema(ReadOnly = true)]` attribute. It tried it:
Requests via Postman work, but in the resulting Swagger UI only the property in the
Artist
class is hidden.[SwaggerSchema(ReadOnly = true)]
does not work for the other parameters.Is this a bug or just a bad design?
Attempt 3: [SwaggerIgnore]
My next approach was to use a custom
[SwaggerIgnore]
Filter. From the multiple versions and variations I found at (https://stackoverflow.com/questions/41005730/how-to-configure-swashbuckle-to-ignore-property-on-model) I chose this one:While debugging I could see that the annotated property is removed from the schema, but it is still being displayed in Swagger UI. The code again works only for body properties.
Attempt 4: [OpenApiParameterIgnore]
I then found another promising solution using IOperationFilter:
This time query, header, and model bound properties are hidden when the are directly in the method parameter list. E.g.:
But it didn't work if the parameters where inside a class, like the examples above.
Partial Workaround
After a lot of debugging and looking at the objects I figured out that in the method the parameters are considered ParameterAttributes, but inside the class they are PropertyAttributes and therefore not selected in the above code.
The solution is to change
metadata.Attributes.ParameterAttributes
tometadata.Attributes.Attributes
. Now both parameter and property attributes are selected and removed.It still doesn't work for the parameter inside the body class, because the Artist class is treated as one property. Flattening doesn't work due to the bug in the API Explorer. I don't understand how to extend the code so that it would work also inside the body. Who can help?
Also the
IOperationFilter
doesn't remove the parameter from the displayed model in SwaggerUI. It requires an additionalISchemaFilter
or the usage of[SwaggerSchema(ReadOnly = true)]
.Conclusion and Feature/UpdateRequest
I'm very frustrated with Swagger and Asp.Net Core. To achieve a basic common pattern that is documented at Microsoft Learn one must jump through hoops and waste valuable time for tricking the framework instead of working on the business domain. Then there is no way out of the box to hide parameters and the extention library doesn't work.
Please update
[SwaggerSchema(ReadOnly = true)]
so that: