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

JSON object/array syntax in <example> XML tags not working #2070

Closed
stevenmccormack opened this issue Mar 25, 2021 · 2 comments
Closed

JSON object/array syntax in <example> XML tags not working #2070

stevenmccormack opened this issue Mar 25, 2021 · 2 comments

Comments

@stevenmccormack
Copy link

I am not able to use the null example tags in XML documentation. as decribed in #1768 (comment)
To ensure the problem is not produced by any special configuration in my project I created a new .NET 5 solution based on the Web API template:

SwaggerTest.csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>

    <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
      <DocumentationFile>bin\Debug\net5.0\SwaggerTest.xml</DocumentationFile>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.1" />
    </ItemGroup>

</Project>

Startup.cs:

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;


namespace SwaggerTest {
    public class Startup {
        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services) {
            services.AddControllers();
            services.AddSwaggerGen(c => { 
                c.SwaggerDoc("v1", new OpenApiInfo {Title = "SwaggerTest", Version = "v1"});
                var filePath = Path.Combine(System.AppContext.BaseDirectory, "SwaggerTest.xml");
                c.IncludeXmlComments(filePath);
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerTest v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
        }
    }
}

WeatherForecast.cs

using System;

namespace SwaggerTest {
    public class WeatherForecast {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public int TemperatureF => 32 + (int) (TemperatureC / 0.5556);

        /// <summary>
        /// This is a test for a string
        /// </summary>
        /// <example>"Hello World!"</example>
        public string Summary { get; set; }

        /// <summary>
        /// This is a test for a string
        /// </summary>
        /// <example>Hello World</example>
        public string UnquotedExampleString { get; set; }

        /// <summary>
        /// This is a test for a string
        /// </summary>
        /// <example>null</example>
        public string NullExampleString { get; set; }

        
        /// <summary>
        /// This is a nullable int
        /// </summary>
        /// <example>null</example>
        public int? SampleIntValue { get; set; }
    }
}

The resulting Sagger Documentation does not pickup the null example:
grafik

@wu-yafeng
Copy link
Contributor

wu-yafeng commented Apr 2, 2021

Create a ExamplesSchemaFilter.cs in your project:

public class ExamplesSchemaFilter : ISchemaFilter
    {
        private readonly XPathNavigator _xmlNavigator;

        public ExamplesSchemaFilter(XPathDocument xmlDoc)
        {
            _xmlNavigator = xmlDoc.CreateNavigator();
        }
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            if (context.MemberInfo != null)
            {
                var fieldOrPropertyMemberName = XmlCommentsNodeNameHelper.GetMemberNameForFieldOrProperty(context.MemberInfo);
                var fieldOrPropertyNode = _xmlNavigator.SelectSingleNode($"/doc/members/member[@name='{fieldOrPropertyMemberName}']");

                if (fieldOrPropertyNode == null) return;

                var exampleNode = fieldOrPropertyNode.SelectSingleNode("example");
                if (exampleNode != null
                    && schema.ResolveType(context.SchemaRepository) == "string")
                {
                    schema.Example = OpenApiAnyFactory.CreateFromJson(exampleNode.InnerXml) ?? new OpenApiNull();
                }
            }
        }
    }

configure the filter in startup ConfigureServices:

 services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi", Version = "v1" });
                Directory.GetFiles(Environment.ContentRootPath, "*.xml", SearchOption.AllDirectories)
                    .ToList().ForEach(file =>
                    {
                        c.IncludeXmlComments(file);
                        c.SchemaFilter<ExamplesSchemaFilter>(new XPathDocument(file));
                    });
            });

@domaindrivendev
Copy link
Owner

domaindrivendev commented Aug 2, 2021

Fixed by #2151. Released with v6.1.5.

@domaindrivendev domaindrivendev removed this from the vNext milestone Aug 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants