12

I followed this up to the xml doc part in order to create Swagger documentation using Swashbuckle. It should allow me to view the endpoints via (in my case):

http://localhost:51854/swagger/ui/index

Unfortunately, I cannot see any endpoints:

enter image description here

Any ideas why and how to fix this? Please note that I created my webapi from an empty webapi project - maybe that's the problem. Something must be missing but I am not sure what ...

I have now identified the following code as the root cause. In Global.asax.cs:

var container = new XyzWebApiStructureMapContainerConfigurator().Configure(GlobalConfiguration.Configuration);
GlobalConfiguration.Configuration.Services
.Replace(typeof(IHttpControllerActivator),
new StructureMapHttpControllerActivator(container));

Some classes:

public class XyzWebApiStructureMapContainerConfigurator
{
    public IContainer Configure(HttpConfiguration config)
    {
        var container = new Container(new BlaWebApiRegistry());
        config.DependencyResolver = new StructureMapDependencyResolver(container);
        return container;
    }
}

public class StructureMapDependencyResolver : StructureMapDependencyScope, IDependencyResolver, IHttpControllerActivator
{
    private readonly IContainer _container;

    public StructureMapDependencyResolver(IContainer container)
        : base(container)
    {
        _container = container;
        container.Inject<IHttpControllerActivator>(this);
    }

    public IDependencyScope BeginScope()
    {
        return new StructureMapDependencyScope(_container.GetNestedContainer());
    }

    public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
    {
        var scope = request.GetDependencyScope();
        return scope.GetService(controllerType) as IHttpController;
    }
}

PS:

Simplified controller code:

[RoutePrefix("api/XYZ")]
public class BlaController : ApiController
{
    private readonly ISomething _something;

    public BlaController(ISomething something)
    {
        _something = something;
    }

    [Route("")]
    [HttpGet]
    public IHttpActionResult Resources([FromUri] BlaRequest blaRequest)
    {
        // something exciting
        return Ok(returnObject);
    }
}

PPS:

More code:

// WebApiConfig

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services  

    // Web API routes
    config.MapHttpAttributeRoutes();

    //var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors();

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

// Global.asax.cs

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);

        GlobalConfiguration.Configuration.Formatters.Clear();
        GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());

        var container = new XyzWebApiStructureMapContainerConfigurator().Configure(GlobalConfiguration.Configuration);
        GlobalConfiguration.Configuration.Services
        .Replace(typeof(IHttpControllerActivator),
            new StructureMapHttpControllerActivator(container));
    }
}

PPPS:

{
swagger: "2.0",
info: {
version: "v1",
title: "Bla.Di.Bla"
},
host: "localhost:51854",
schemes: [
"http"
],
paths: { },
definitions: { }
}
strickt01
  • 3,959
  • 1
  • 17
  • 32
cs0815
  • 16,751
  • 45
  • 136
  • 299
  • What are the names of your Controller classes? Sometimes this is just caused by not having the classes suffixed with "Controller". e.g. ProductController.cs etc. Other details of your endpoints such as whether the routing is set up using attribute routing or convention-based routing would also be helpful. – strickt01 May 04 '16 at 17:09
  • @strickt01 - thanks. I added some controller sample code. – cs0815 May 04 '16 at 19:12
  • Are you using OWIN? If so [this might help](http://stackoverflow.com/questions/31840165/swashbuckle-5-cant-find-my-apicontrollers). – strickt01 May 04 '16 at 20:18
  • what are your swagger.json contents that are obtained at http://localhost:51854/swagger/docs/v1 ? – Sampada May 05 '16 at 05:24
  • @strickt01 Owin is referenced but not sure if it is used. Our infrastructure expert had to make some adjustments to get things working in IIS for remote ajax requests. I have added more code. Please have a look at PPS. – cs0815 May 05 '16 at 07:32
  • @Sampada - please see PPPS. Thanks. – cs0815 May 05 '16 at 08:46
  • Ok. This shows no APIs are being generated at the json level itself. My best guess here on why this is happening is lack of a basePath. Please try setting it in the swagger bean config. – Sampada May 05 '16 at 09:17
  • @Sampada - thanks. Bit confused now. This is Java stuff so would not apply in my .Net/Swashbuckle scenario. – cs0815 May 05 '16 at 12:38
  • Well, there should be a way to set the basePath in Swashbuckle as well. Agree that bean config is java stuff. – Sampada May 05 '16 at 12:46
  • I have identified the code in the Global.asax.cs as the root cause. see edited question. – cs0815 May 05 '16 at 15:23
  • I'm facing same problem and after truns out above line swagger is working fine. But, DI was broken. Any alternative to above without comment? – Prasad Kanaparthi Feb 19 '19 at 04:02

6 Answers6

3

Turns out this line:

config.DependencyResolver = new StructureMapDependencyResolver(container);

in the question's class XyzWebApiStructureMapContainerConfigurator caused some issues.

Hope this helps someone in the future.

cs0815
  • 16,751
  • 45
  • 136
  • 299
  • I'm facing same problem and after truns out above line swagger is working fine. But, DI was broken. Any alternative to above without comment? – Prasad Kanaparthi Feb 19 '19 at 04:02
  • This doesn't seem like a solution. Is the issue that the SwaggerConfig is in the same namespace as the DI registration class? – ryanwebjackson Mar 20 '20 at 03:40
3

Had the same issue. Turns out the DI (Unity in my case) was configured to bind all loaded assemblies (one of which is Swashbuckle.Core).

Just a bit of refining which assemblies get binded has solved the issue:

var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(asm => asm.FullName.StartsWith("MySolution.MyProject"));

// Web API configuration and services
var container = new UnityContainer();
container.RegisterTypes(
    AllClasses.FromAssemblies(assemblies),
    WithMappings.FromMatchingInterface,
    WithName.Default);

config.DependencyResolver = new UnityDependencyResolver(container);
BogdanB
  • 183
  • 1
  • 1
  • 6
1

I faced same issue with swagger and took me long hours to search for solution. Finally got one. Add [HttpGet] or [HttpPost] attribute to each of controller's action method.

[HttpPost]
public IActionResult TestMethod()
 {
  //// Some code
 }
Nitika
  • 41
  • 4
0

I realise this is an old issue, but I've just encountered it & have a different solution to the ones already suggested. I hope its of use to anyone else getting the problem.

The issue was caused by Structuremap scanning. I had the following lines of code in my Structuremap.Registry class

Scan(scan =>
{
    ....
    scan.AssembliesFromApplicationBaseDirectory();
    scan.TheCallingAssembly();
    scan.WithDefaultConventions();
});

The line

scan.AssembliesFromApplicationBaseDirectory();

was stopping Swagger working. I've changed it to

scan.AssembliesFromApplicationBaseDirectory(MyDllsPathFilter());

and now Swagger is working as expected.

daveD
  • 869
  • 1
  • 7
  • 24
0

In my case the issue was caused by IIS Express Virtual Directory, here is the detailed explanation:

I have an API project, this is how the project properties looks like:

enter image description here

These properties are written to applicationhost.config file, located at: MySolutionPath\.vs\MySolution\config

This is the section of the file which stores the Virtual Directory information:

<sites>
  <site name="MyProject" id="3">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
      <virtualDirectory path="/" physicalPath="C:\MyProjectPath\MyProject" />
    </application>
    <bindings>
      <binding protocol="https" bindingInformation="*:44334:localhost" />
      <binding protocol="http" bindingInformation="*:53242:localhost" />
    </bindings>
  </site>
  ..
</sites>

Everything was working fine...

Then I started following this guide, which asked me to change the Project URL to: https://localhost:44334/Swagger

enter image description here

I did so and then clicked on Create Virtual Directory button.

Doing so made the following change to applicationhost.config file:

<sites>
  <site name="MyProject" id="3">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
      <virtualDirectory path="/" physicalPath="C:\MyProjectPath\MyProject" />
    </application>
    <application path="/Swagger" applicationPool="Clr4IntegratedAppPool">
      <virtualDirectory path="/" physicalPath="C:\Shopless\shopless.source\Shopless.Api" />
    </application>
    <bindings>
      <binding protocol="https" bindingInformation="*:44334:localhost" />
      <binding protocol="http" bindingInformation="*:53242:localhost" />
    </bindings>
  </site>
  ..
</sites>

And that was the issue, because now the path /Swagger points to the root of my project.

To fix the issue, I had to delete the new section from applicationhost.config file and also and change the Project Url back to it's original value.

Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
0

You need to suppress custom headers for content-security-policy. These headers block the swagger js from execution.

Before removing headers Before removing headers

Commented content-security-policy Commented content-security-policy

Swagger UI with endpoints after removing headers Swagger UI with endpoints after removing headers

Tanjot
  • 31
  • 4