Skip to content
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

[Bug]: In the Apply method of the IOperationFilter interface, all schemas in operation.RequestBody.Content are either null or have a Count of 0. #3017

Open
MuQuanyu opened this issue Aug 9, 2024 · 3 comments
Labels
bug stale Stale issues or pull requests

Comments

@MuQuanyu
Copy link

MuQuanyu commented Aug 9, 2024

Describe the bug

In the Apply method of the IOperationFilter interface, all schemas in operation.RequestBody.Content are either null or have a Count of 0.I've tested a lot of things like public string testiges noreparams ([FromBody] Person person)
{
return $"{person.Id},{person.Name},{person.Gender},{person.Age}";
Such an interface has also changed the entity class type of many request bodies, but it is still in the filter and cannot get those parameters.

Expected behavior

Since I want to filter out some of the attributes in the request body that are generated on swagger, to implement this also annotate, then I have to take advantage of your filter! This is to implement the Apply method in the IOperationFilter interface. But I can't get the Schema of the request body, which makes me unable to implement this feature, I can only use reflection mechanism to enforce the implementation.

Actual behavior

What actually happens is that you don't get it. And I also enforced the use of reflection to fulfill my needs. The code snippet is attached.

Steps to reproduce

No response

Exception(s) (if any)

No response

Swashbuckle.AspNetCore version

6.7.0

.NET Version

net6.0

Anything else?

using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication2.Attributes.Filter
{
public class IgnoreParamsOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var ignoreParamsAttribute = context.MethodInfo
.GetCustomAttributes(true)
.OfType()
.FirstOrDefault();

        if (ignoreParamsAttribute != null && operation.RequestBody != null)
        {
            foreach (var content in operation.RequestBody.Content)
            {
                var schema = content.Value.Schema;

                // 动态生成 Schema,如果它为空或未初始化
                if (schema == null || schema.Properties.Count == 0)
                {
                    var parameterType = context.MethodInfo.GetParameters()
                        .FirstOrDefault(p => p.GetCustomAttribute<FromBodyAttribute>() != null)?.ParameterType;

                    if (parameterType != null)
                    {
                        schema = GenerateSchemaFromType(parameterType, ignoreParamsAttribute.ParamsToIgnore);
                        content.Value.Schema = schema;
                    }
                }
            }
        }
    }

    private OpenApiSchema GenerateSchemaFromType(Type type, string[] paramsToIgnore)
    {
        var schema = new OpenApiSchema
        {
            Type = "object",
            Properties = new Dictionary<string, OpenApiSchema>()
        };

        // 使用反射获取所有公共属性并生成 Schema
        var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (var prop in properties)
        {
            if (!paramsToIgnore.Contains(prop.Name))
            {
                var propSchema = new OpenApiSchema
                {
                    Type = GetOpenApiType(prop.PropertyType),
                    Description = GetPropertyDescription(prop),
                    Format = GetOpenApiFormat(prop.PropertyType)
                };

                schema.Properties.Add(Char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1), propSchema);
            }
        }

        return schema;
    }

    private string GetOpenApiType(Type type)
    {
        if (type == typeof(int) || type == typeof(long))
            return "integer";
        if (type == typeof(float) || type == typeof(double) || type == typeof(decimal))
            return "number";
        if (type == typeof(bool))
            return "boolean";
        if (type == typeof(string))
            return "string";
        if (type.IsArray || (type.IsGenericType && typeof(IEnumerable<>).IsAssignableFrom(type.GetGenericTypeDefinition())))
            return "array";

        return "object"; // 默认类型为 object
    }

    private string GetOpenApiFormat(Type type)
    {
        if (type == typeof(int))
            return "int32";
        if (type == typeof(long))
            return "int64";
        if (type == typeof(float))
            return "float";
        if (type == typeof(double) || type == typeof(decimal))
            return "double";
        if (type == typeof(DateTime))
            return "date-time";

        return null; // 默认没有 format
    }

    private string GetPropertyDescription(PropertyInfo prop)
    {
        // 可以在此扩展,使用注解或其他方式为属性生成描述
        return prop.Name;
    }
}

}

@MuQuanyu MuQuanyu added the bug label Aug 9, 2024
@martincostello
Copy link
Collaborator

It may be the case that you're seeing the intermediate state when the document is in the process of being built-up and that the information isn't available yet.

What do you see if you inspect the operations as part of a document filter?

FYI there's information here about when each type of filter runs: #2993 (comment)

@jgarciadelanoceda
Copy link
Contributor

jgarciadelanoceda commented Sep 10, 2024

Seeing the filter that you have created it's very similar to what the SwagerIgnoreAttribute makes under the hood, so you could take a look there.

If it's not the same I need a repro to look at it

Copy link
Contributor

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.

@github-actions github-actions bot added the stale Stale issues or pull requests label Nov 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug stale Stale issues or pull requests
Projects
None yet
Development

No branches or pull requests

3 participants