4

Since a lot of attributes are designed by avoid unsealed attributes I'm searching for a solution for setting an attributes value (my first idea was to inherit the class and set a constructor what checks the web-config - not possible with a sealed class):

There's the ApiExplorerSettingsAttribute in namespace System.Web.Http.Description

I want the following API-action to get hidden in the case, a value in web-config is false:

<Api.Properties.Settings>
  <setting name="Hoster">
    <value>False</value>
  </setting>
</Api.Properties.Settings>

the action would look like this:

[HttpGet, Route("api/bdlg")]
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(BdlgDataStorage))]
[ApiExplorerSettings(IgnoreApi = Properties.Settings.Default.Hoster)]
private async Task<BdlgDataStorage> GetBdlgStorageValues()
{
    using (var context = new BdlgContext())
        return context.BdlgDataStorages
            .Include(s=>s.ChangeTrack)
            .Where(w=>w.Isle > 56)
            .Select(selectorFunction)
            .ToListAsync();
}

The important line is:

[ApiExplorerSettings(IgnoreApi = Properties.Settings.Default.Hoster)]

Here, I get a compiler-error:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

Anyone got any idea, how I can set the value of IgnoreApi the same as the one from web-config?

Matthias Burger
  • 5,549
  • 7
  • 49
  • 94

3 Answers3

4

You can't. Attributes are compiled statically into the assembly. They belong to the metadata of a member. You can't change attributes at run-time.

You have to find another way to influence the ApiExplorerSettings. This post seems to be what you are looking for: Dynamically Ignore WebAPI method on controller for api explorer documentation.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
1

Another possible solution I found is by using preprocessor directives (this would have been enough for me, since the action only should be visible in swagger when it's DEBUG):

#if DEBUG
    [ApiExplorerSettings(IgnoreApi = false)]
#else
    [ApiExplorerSettings(IgnoreApi = true)]
#endif
    [SwaggerResponse(HttpStatusCode.OK, Type = typeof(BdlgDataStorage))]
    [HttpGet, Route("api/bdlg")]
    private async Task<BdlgDataStorage> GetBdlgStorageValues()
    {
        using (var context = new BdlgContext())
            return context.BdlgDataStorages
                .Include(s=>s.ChangeTrack)
                .Where(w=>w.Isle > 56)
                .Select(selectorFunction)
                .ToListAsync();
    }
Shai Cohen
  • 6,074
  • 4
  • 31
  • 54
Matthias Burger
  • 5,549
  • 7
  • 49
  • 94
0

ref to https://joonasw.net/view/hide-actions-from-swagger-openapi-documentation-in-aspnet-core I'm doing this for test action or controller:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TestSwaggerAttribute : Attribute { }

public class ActionHidingConvention : IActionModelConvention
{
    private readonly Boolean isDevelopment;

    public ActionHidingConvention(IWebHostEnvironment env)
    {
        isDevelopment = env.IsDevelopment();
    }

    public void Apply(ActionModel action)
    {
        if (!isDevelopment && (
            action.Controller.Attributes.Any(x => x.GetType() == typeof(TestSwaggerAttribute))
            || action.Attributes.Any(x => x.GetType() == typeof(TestSwaggerAttribute))))
            action.ApiExplorer.IsVisible = false;
    }
}

and on program.cs:

builder.Services
    .AddControllers(c =>
    {
        c.Conventions.Add(new ActionHidingConvention(builder.Environment));
    })

Ex:

[HttpPost, TestSwagger]
public async Task<IActionResult> TestCreateAsync([FromBody] Something info) {...}

or

[ApiController, Route("api/[controller]", TestSwagger)]
public class ProductController : Controller {...}