2016-12-02 34 views
6

Mamy core webapi asp.net. Dodaliśmy Microsoft.AspNetCore.Mvc.Versioning i Swashbuckle, aby uzyskać interfejs użytkownika przechwytu. Mamy określone kontrolery jak ten:Jak skonfigurować Swashbuckle vs Microsoft.AspNetCore.Mvc.Versioning

[ApiVersion("1.0")] 
[Route("api/v{version:apiVersion}/[controller]")] 
public class ContactController : Controller 
{ 

Kiedy prowadzimy Swagger ui mamy wersję jako parametr w trasach: enter image description here

Jak konfiguracji domyślnej „v1” na trasie? Jeśli wersja 2 pojawi się na etapie, w jaki sposób obsługa interfejsu użytkownika ui dla obu wersji?

+0

Ktoś otworzył GitHub problem konkretnie o tym, a gdy jest jeszcze otwarty na dzień 7 stycznia 2017, komentarze mieć obejście że pracuje dla mnie: https: // GitHub. com/domaindrivendev/Swashbuckle.AspNetCore/issues/244 –

Odpowiedz

2

W tej chwili Swashbuckle i Microsoft.AspNetCore.Mvc.Versioning są znajomymi. Działa dobrze. Właśnie stworzyłem projekt testowy w VS2017 i sprawdziłem, jak działa.

Pierwsza to te pakiety dwa Nuget:

<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="1.2.1" /> 
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" /> 

Konfiguruj wszystko w Startup.cs (czytaj moje komentarze):

public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddMvc(); 


     // Configure versions 
     services.AddApiVersioning(o => 
     { 
      o.AssumeDefaultVersionWhenUnspecified = true; 
      o.DefaultApiVersion = new ApiVersion(1, 0); 
     }); 

     // Configure swagger 
     services.AddSwaggerGen(options => 
     { 
      // Specify two versions 
      options.SwaggerDoc("v1", 
       new Info() 
       { 
        Version = "v1", 
        Title = "v1 API", 
        Description = "v1 API Description", 
        TermsOfService = "Terms of usage v1" 
       }); 

      options.SwaggerDoc("v2", 
       new Info() 
       { 
        Version = "v2", 
        Title = "v2 API", 
        Description = "v2 API Description", 
        TermsOfService = "Terms of usage v2" 
       }); 

      // This call remove version from parameter, without it we will have version as parameter 
      // for all endpoints in swagger UI 
      options.OperationFilter<RemoveVersionFromParameter>(); 

      // This make replacement of v{version:apiVersion} to real version of corresponding swagger doc. 
      options.DocumentFilter<ReplaceVersionWithExactValueInPath>(); 

      // This on used to exclude endpoint mapped to not specified in swagger version. 
      // In this particular example we exclude 'GET /api/v2/Values/otherget/three' endpoint, 
      // because it was mapped to v3 with attribute: MapToApiVersion("3") 
      options.DocInclusionPredicate((version, desc) => 
      { 
       var versions = desc.ControllerAttributes() 
        .OfType<ApiVersionAttribute>() 
        .SelectMany(attr => attr.Versions); 

       var maps = desc.ActionAttributes() 
        .OfType<MapToApiVersionAttribute>() 
        .SelectMany(attr => attr.Versions) 
        .ToArray(); 

       return versions.Any(v => $"v{v.ToString()}" == version) && (maps.Length == 0 || maps.Any(v => $"v{v.ToString()}" == version)); 
      }); 

     }); 

    } 

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 

     app.UseSwagger(); 
     app.UseSwaggerUI(c => 
     { 
      c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"v2"); 
      c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"v1"); 
     }); 
     app.UseMvc(); 
    } 

Istnieją dwie klasy, które czynią ten trick:

public class RemoveVersionFromParameter : IOperationFilter 
{ 
    public void Apply(Operation operation, OperationFilterContext context) 
    { 
     var versionParameter = operation.Parameters.Single(p => p.Name == "version"); 
     operation.Parameters.Remove(versionParameter); 
    } 
} 

public class ReplaceVersionWithExactValueInPath : IDocumentFilter 
{ 
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) 
    { 
     swaggerDoc.Paths = swaggerDoc.Paths 
      .ToDictionary(
       path => path.Key.Replace("v{version}", swaggerDoc.Info.Version), 
       path => path.Value 
      ); 
    } 
} 

The RemoveVersionFromParameter usuwa interfejs użytkownika przechwytującego to pole tekstowe:

enter image description here

ReplaceVersionWithExactValueInPath zmiany to:

enter image description here

do tego:

enter image description here

klasa Kontroler wygląda teraz następująco:

[Route("api/v{version:apiVersion}/[controller]")] 
[ApiVersion("1")] 
[ApiVersion("2")] 
public class ValuesController : Controller 
{ 
    // GET api/values 
    [HttpGet] 
    public IEnumerable<string> Get() 
    { 
     return new string[] { "value1", "value2" }; 
    } 

    // GET api/values/5 
    [HttpGet("{id}")] 
    public string Get(int id) 
    { 
     return "value"; 
    } 

    // POST api/values 
    [HttpPost] 
    public void Post([FromBody]string value) 
    { 
    } 

    // PUT api/values/5 
    [HttpPut("{id}")] 
    public void Put(int id, [FromBody]string value) 
    { 
    } 

    // DELETE api/values/5 
    [HttpDelete("{id}")] 
    public void Delete(int id) 
    { 
    } 


    [HttpGet("otherget/one")] 
    [MapToApiVersion("2")] 
    public IEnumerable<string> Get2() 
    { 
     return new string[] { "value1", "value2" }; 
    } 

    /// <summary> 
    /// THIS ONE WILL BE EXCLUDED FROM SWAGGER Ui, BECAUSE v3 IS NOT SPECIFIED. 'DocInclusionPredicate' MAKES THE 
    /// TRICK 
    /// </summary> 
    /// <returns></returns> 
    [HttpGet("otherget/three")] 
    [MapToApiVersion("3")] 
    public IEnumerable<string> Get3() 
    { 
     return new string[] { "value1", "value2" }; 
    } 
} 

Kod: https://gist.github.com/Alezis/bab8b559d0d8800c994d065db03ab53e