2015-08-05 14 views
17

Sono a un punto in cui ho davvero bisogno della documentazione API per il mio progetto WebAPI 2 e ho utilizzato il pacchetto NuGet di Swashbuckle 5. Fuori dalla scatola, posso colpire {myrooturl}/swagger e compare un'interfaccia utente, ma non ci sono controller, metodi o altro. Solo il titolo: [URL base: /EM.Services, versione api: v1]Swashbuckle 5 non riesce a trovare i miei ApiController

Ho dato un'occhiata ai documenti di Swashbuckle e, poiché sto usando OWIN che è ospitato da IIS, ho modificato SwaggerConfig con:

c.RootUrl(req => req.RequestUri.GetLeftPart(UriPartial.Authority) + req.GetRequestContext().VirtualPathRoot.TrimEnd('/')); 

di cui al presente documento: https://github.com/domaindrivendev/Swashbuckle/blob/1326e753ce9b3a823b3c156b0b601134692ffc58/README.md#transitioning-to-swashbuckle-50

ho anche impostare la costruzione del progetto di generare i documenti XML e indicai il mio SwaggerConfig ad essa con:

private static string GetXmlCommentsPath() 
    { 
     // tried with an without the \bin 
     return String.Format(@"{0}\bin\EM.Services.XML", AppDomain.CurrentDomain.BaseDirectory); 
    } 

Non sono sicuro che i documenti XML funzionanti/non funzionanti abbiano qualcosa a che fare con questo, dato che non ottengo assolutamente alcun controller sulla pagina swagger-ui.

Per quello che vale, tutto il mio controller eredita da un BaseController, che a sua volta eredita da ApiController.

C'è qualcosa di strano con il mio WebApiConfig?

public static void Register(HttpConfiguration config) 
    { 

     config.SuppressDefaultHostAuthentication(); 
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 

     config.Filters.Add(new ValidateModelAttribute()); 

     config.Filters.Add(new BaseAuthenticationAttribute()); 

     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{action}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

     var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); 
     jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
     jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 
    } 

miei controllori concreti sembrano tutti come questo (ho provato subbing fuori BaseController per ApiController e non v'è nessun cambiamento):

[RoutePrefix("api/whatever")] 
public class FooController : BaseController 

e il mio controller di base non fa molto (ancora) , ha solo un attributo:

[BuildClaims] 
public abstract class BaseController : ApiController 

La pagina vuota persiste utilizzando IIS Express o IIS completo.

Aggiornamento: Esempio di un controller inventato ho fatto che è davvero di base. Inoltre non si presenta, dato che ho ancora lo swagger del piatto della caldaia ui con niente in esso.

/// <summary> 
/// I am a test 
/// </summary> 
[RoutePrefix("api/dummy")] 
public class DummyController : ApiController 
{ 
    [HttpGet] 
    [Route("foo")] 
    public int Foo() 
    { 
     return 42; 
    } 
} 

risposta

18

ho trovato il problema. Dopo aver creato un progetto di test vuoto, ho notato che WebApiConfiguration veniva registrato dall'avvio dell'app global.asax e non dalla classe di avvio OWIN (come ho fatto io).

Dato che Swagger/Swashbuckle si sta collegando a GlobalConfiguration e anche dato che l'avvio di OWIN e Global.asax vivono in contesti diversi (credo), la soluzione è quella di cablare il materiale WebAPI per registrarsi da Global.asax e avere L'oggetto dell'app OWIN utilizza WebAPI.

bit rilevanti:

// global asax 
    protected void Application_Start(object sender, EventArgs e) 
    { 
     GlobalConfiguration.Configure(WebApiConfig.Register); 
     // ... more stuff 
    } 

    //startup.cs 
    public void Configuration(IAppBuilder app) 
    { 
     // This must happen FIRST otherwise CORS will not work. 
     app.UseCors(CorsOptions.AllowAll); 

     HttpConfiguration config = new HttpConfiguration(); 

     ConfigureAuth(app); 

     // webapi is registered in the global.asax 
     app.UseWebApi(config); 

    } 

Dopo ricablaggio come sopra, possono ora vedere controllori & azioni nel spavalderia UI.

0

Swashbuckle si trova sulla cima del livello di metadati di WebAPI ApiExplorer. Prende le descrizioni delle operazioni da ApiExplorer e quindi le associa alle descrizioni Swagger.

Dal momento che il controller eredita da BaseController e non APICONTROLLER non funzionerà

Per JimWolleys commentano

private IEnumerable<ApiDescription> GetApiDescriptionsFor(string apiVersion) 
    { 
     return (_options.VersionSupportResolver == null) 
      ? _apiExplorer.ApiDescriptions 
      : _apiExplorer.ApiDescriptions.Where(apiDesc => _options.VersionSupportResolver(apiDesc, apiVersion)); 
    } 

questo è il metodo che i poteri Swashbuckle per ottenere tutte le chiamate API. Ci vuole un IApiExplorer. Che se non è stato modificato per prendere qualcosa di diverso, viene fornito il predefinito ApiExplorer fornito. Che ha solo le informazioni di cose che ereditano da ApiController

Swashbuckle git repo. just search for GetApiDescriptionsFor and it will take you straight to the method

+0

Esiste un pacchetto di documentazione API che supporta questo scenario? Inoltre, ho creato un controller fittizio che eredita da ApiController come un normale controller, e che non appare nemmeno nel swagger ui. –

+0

Non so se c'è un pacchetto API che lo faccia fuori dalla scatola. Se potessi pubblicare il codice per il controller fittizio o semplicemente caricare il tuo progetto da qualche parte potrei farlo risolverlo – gh9

+0

dummy controller aggiunto –

8

Mi sono bloccato ... e queste risposte non mi hanno aiutato completamente ... anche se mi hanno condotto lì. Proprio per salvare altre persone po 'di tempo:

Devi passare alla configurazione http da OWIN e quindi registrare su che invece di utilizzare la classe GlobalConfiguration in questo modo:

//starup.cs 
public void Configuration(IAppBuilder app) 
    { 
     Config = new HttpConfiguration(); 
     WebApiConfig.Register(Config); 

     app 
      .UseResponseLogging() 
      .UseRequestLogging() 
      .UseHttpErrors() 
      .UseExceptionLogging() 
      .UseWebApi(Config); 

     HandlerConfig.Register(Config); 

     SwaggerConfig.Register(Config); 
    } 

e nel file spavalderia di configurazione, il cambiamento il metodo di registrazione a:

public static void Register(HttpConfiguration config) 
    { 
     var thisAssembly = typeof(SwaggerConfig).Assembly; 

     config 
      .EnableSwagger(c => 
       {... 

Spero che questo aiuti.

0

Ho trovato questo collegamento molto utile. Questa particolare soluzione è specifica per l'API Microsoft.Azure.Mobile.Server, ma per me ha risolto il problema.

Azure Mobile Apps Server and Swagger

1

ho scoperto che ho avuto lo stesso problema. Ho creato un metodo di estensione per aiutare

using Swashbuckle.Application; 
using System.Web.Http; 

public static class SwaggerExtensions 
{ 
    public static HttpConfiguration EnableSwagger(this HttpConfiguration httpConfiguration) 
    { 
     httpConfiguration 
      .EnableSwagger(c => c.SingleApiVersion("v1", "A title for your API")) 
      .EnableSwaggerUi(); 
     return httpConfiguration; 
    } 
} 

poi nella mia Startup.cs

public class Startup 
{ 
    public void Configuration(IAppBuilder appBuilder) 
    { 
     HttpConfiguration httpConfiguration = new HttpConfiguration(); 

     httpConfiguration 
      .EnableSwagger() // <==== EXTENSION METHOD <==== // 
      .MapHttpAttributeRoutes(); 

     httpConfiguration.Routes.MapHttpRoute(
      "DefaultApi", 
      "api/{controller}/{id}", 
      new {id = RouteParameter.Optional}); 

     appBuilder 
      .UseWebApi(httpConfiguration); 
    } 
} 
3

Tutte queste soluzioni funziona per me, ma tutti sono hack solo brutto per il mio problema. Dopo poche ore di indagine ho scoperto che il problema è che uso anche Glimpse (o altri pacchetti che cambiano la tabella di routing).

Qui è un grande sintesi: https://github.com/domaindrivendev/Swashbuckle/issues/468#issuecomment-139246748

  1. Glimpse aggiunge proxy castello in cima HttpWebRoute. Quindi HostedHttpRouteCollection è la raccolta di RouteProxy e non HttpWebRoute.
  2. La classe APIExplorer ha il metodo FlattenRoutes che esegue un ciclo foreach su HostedHttpRouteCollection.
  3. GetEnumerator attuazione HostedHttpRouteCollection specificamente cercare HttpWebRoute. Guarda il codice qui sotto. Poiché glimpse ha aggiunto dei proxy, l'enumeratore restituisce sempre 0 percorsi !!

    public override IEnumerator GetEnumerator() 
    { 
        // Here we only care about Web API routes. 
        return _routeCollection 
         .OfType() 
         .Select(httpWebRoute => httpWebRoute.HttpRoute) 
         .GetEnumerator(); 
    }

Sono affraid non esiste una soluzione, è possibile scegliere ciò che si desidera utilizzare: Swashbuckle o Glimpse, ma non entrambi insieme.

Ovviamente si può provare a eseguire uno di questi metodi, ma c'è il rischio di comportamenti imprevisti e bug insidiosi.

0

Ho appena avuto lo stesso problema e nessuno di questi mi ha aiutato.

Dopo alcuni scherzi, ho capito che i percorsi che avevo etichettato come [System.Web.Mvc.Route("visit")] non venivano scoperti da spavalderia.

[HttpGet] 
    // ROUTE ATTRIBUTE NOT FOUND BY SWAGGER 
    [System.Web.Mvc.Route("visit")] 
    public string Visit() 
    { 

ma [System.Web.Http.Route("visit")] è

[HttpGet] 
    // ROUTE ATTRIBUTE *IS* FOUND BY SWAGGER 
    [System.Web.Http.Route("visit")] 
    public string Visit() 
    { 

Sono sicuro al 100%, ma se è importante, ho anche passato da

public class MyAPIController : Controller 

a:

public class MyAPIController : System.Web.Http.ApiController 

Più precisamente ho rimosso "s usando" tatement per System.Web.Mvc, ma il codice è elencato a scopo illustrativo.

Spero che questo aiuti qualcun altro in futuro :) Buona fortuna!

Problemi correlati