2016-12-02 57 views
6

我們有asp.net核心webapi。我們添加了Microsoft.AspNetCore.Mvc.VersioningSwashbuckle以使用戶界面更加流暢。 我們指定的控制器,因爲這:如何設置Swashbuckle vs Microsoft.AspNetCore.Mvc.Versioning

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

當我們運行招搖的用戶界面,我們得到的版本在路線參數: enter image description here

如何建立默認的「V1」的路線? 如果版本2到達舞臺如何支持兩個版本的swagger ui?

+0

有人專門開了一個Github的問題,關於這個,雖然它仍然爲2017年1月7日的開放,評論有一個正在爲我的解決方法:https://開頭github上。 COM/domaindrivendev/Swashbuckle.AspNetCore /問題/ 244 –

回答

2

目前Swashbuckle和Microsoft.AspNetCore.Mvc.Versioning是朋友。它運作良好。我剛剛在VS2017中創建了測試項目,並檢查了它的工作原理。

首先包括這兩個的NuGet包:

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

配置一切Startup.cs(讀我的意見):

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(); 
    } 

有兩個類來實現這一目的:

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 
      ); 
    } 
} 

RemoveVersionFromParameter從swagger用戶界面中刪除此文本框:

enter image description here

ReplaceVersionWithExactValueInPath改變這樣的:

enter image description here

這樣:現在

enter image description here

Controller類看起來如下:

[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" }; 
    } 
} 

代碼:https://gist.github.com/Alezis/bab8b559d0d8800c994d065db03ab53e