可选参数在Swashbuckle.AspNetCore中导致null异常

时间:2017-10-07 06:21:51

标签: c# swagger asp.net-core-2.0 swashbuckle api-versioning

我有一个带有可选(和可为空)参数的asp.net core 2.0 api控制器操作。当此参数出现在方法签名中时,Swashbuckle.AspNetCore 1.0.0生成的Swagger文档会失败,但如果我从签名中删除它,则会成功。可选参数似乎是错误的原因,但我无法说明原因......

我正在使用Swashbuckle与aspnet-api版本集成: https://github.com/Microsoft/aspnet-api-versioning/wiki/Swashbuckle-Integration

控制器操作

[HttpGet("{id}")]
public IActionResult GetPerson(int id, [FromQuery] bool? includeContactInfo = null)
{
    var includeInfo = (includeContactInfo.HasValue && includeContactInfo.Value == true);
    var person = _repo.GetPerson(id, includeInfo);
    if (person == null)
    {
        return NotFound();
    }

    if (includeInfo)
    {
        // using AutoMapper to map between entity and dto
        var personFullDto = Mapper.Map<PersonFullDto>(person);
        return Ok(personFullDto);
    }

    var personBasicDto = Mapper.Map<PersonBasicDto>(person);
    return Ok(personBasicDto);
}

以下是startup.cs中的配置服务配置方法:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore().AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");
    services.AddMvc();

    services.AddApiVersioning(o =>
    {
        o.ReportApiVersions = true;
        o.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(1, 0);
    });

    services.AddSwaggerGen(options =>
    {
        var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
        foreach (var description in provider.ApiVersionDescriptions)
        {
            options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
        }
        options.OperationFilter<SwaggerDefaultValues>();
        options.IncludeXmlComments(XmlCommentsFilePath);
    });

    var connectString = Startup.Configuration["connectionStrings:ContactsAppDb"];
    services.AddDbContext<ContactsDbContext>(o => o.UseSqlServer(connectString));
    services.AddScoped<IContactsRepository, ContactsRepository>();
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApiVersionDescriptionProvider provider)
{
    if (env.IsEnvironment("PROD"))
    {
        app.UseExceptionHandler();
    }
    else
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseStatusCodePages();

    AutoMapper.Mapper.Initialize(cfg =>
    {
        cfg.CreateMap<Entities.Person, Models.PersonBasicDto>();
        cfg.CreateMap<Entities.Person, Models.PersonFullDto>();
        cfg.CreateMap<Entities.ContactInfo, Models.ContactInfoDto>();
    });

    app.UseMvc();

    app.UseSwagger();
    app.UseSwaggerUI(options =>
    {
        // build a swagger endpoint for each discovered API version
        foreach (var description in provider.ApiVersionDescriptions)
        {
            options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
        }
    });
}

我也在使用SwaggerDefaultValues.cs类 https://github.com/Microsoft/aspnet-api-versioning/wiki/Swashbuckle-Integration#aspnet-core

public class SwaggerDefaultValues : IOperationFilter
{
    public void Apply( Operation operation, OperationFilterContext context )
    {
        foreach ( var parameter in operation.Parameters.OfType<NonBodyParameter>() )
        {
            var description = context.ApiDescription
                                     .ParameterDescriptions
                                     .First( p => p.Name == parameter.Name );

            if ( parameter.Description == null )
            {
                parameter.Description = description.ModelMetadata.Description;
            }

            if ( parameter.Default == null )
            {
                parameter.Default = description.RouteInfo.DefaultValue;
            }

            parameter.Required |= !description.RouteInfo.IsOptional;
        }
    }
}

当我导航到Swagger URL时,以下代码行失败(在SwaggerDefaultValues.cs类中):

parameter.Default = description.RouteInfo.DefaultValue;

当我检查description可选/查询参数的includeContactInfo对象时,description.RouteInfo为空。

错误讯息:

Object reference not set to an instance of an object.

堆栈跟踪:

at ContactsApp.Services.SwaggerDefaultValues.Apply(Operation operation, OperationFilterContext context) in C:\Users\me\Documents\Visual Studio 2017\Projects\ContactsApp\ContactsApp\Services\SwaggerDefaultValues.cs:line 37
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreateOperation(ApiDescription apiDescription, ISchemaRegistry schemaRegistry)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.CreatePathItem(IEnumerable`1 apiDescriptions, ISchemaRegistry schemaRegistry)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwagger(String documentName, String host, String basePath, String[] schemes)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.<Invoke>d__6.MoveNext()

1 个答案:

答案 0 :(得分:1)

使用空条件运算符:

parameter.Default = description.RouteInfo?.DefaultValue;