Conditionally disable ASP.NET MVC Controller
Asked Answered
M

4

20

What is the best way to disable ASP.NET MVC controller conditionally?

I want to have an access to the controller actions if some value in web.config is "true" and 404 if it's "false"

Should I write my own attribute?

UPDATE: Looking for more elegant solution than action filter attribute (with an ability to pass not constant parameter to attribute constructor)

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public class CloseForSomeSettingAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            bool mySettingValue = MySettingManager.GetMySettingValue();

            if (mySettingValue)
            {
                filterContext.Result = new HttpStatusCodeResult(404);
            }
            else
            {
                base.OnActionExecuting(filterContext);
            }
        }
    }
Manton answered 22/7, 2012 at 23:17 Comment(0)
L
6

The easiest would probably be to implement a custom action filter:

http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

You can also conditionally add a route that matches that controller that would result in a 404 being returned.

Lermontov answered 23/7, 2012 at 0:52 Comment(4)
thanks. have written the action filter attribute (see my comment). but maybe some more elegant solution exists?Manton
I don't know your purpose here but perhaps it's best not to do this at the application level? I'm thinking using IIS url-rewrite module to setup rules for the routes you're looking to return 404. Take a look at the examples below:blogs.iis.net/ruslany/archive/2009/04/08/…Lermontov
no. I need to have an ability to switch it from a web.config file.Manton
the rules for url-rewrite are stored in the web.configLermontov
G
3

Answered here - Prevent ASP.NET Core discovering Controller in separate assembly

This approach doesn't need filters, and hides controller from swagger etc.

Gowan answered 13/11, 2020 at 16:18 Comment(0)
S
0

Cross posting from: https://mcmap.net/q/664577/-webapi-help-pages-disable-for-production-release

My solution for disabling ApiController controller:

  • Uses WebConfig AppSettings config flag instead of (#if DEBUG)
  • Before method is invoked ExecuteAsync intercepts the invocation and checks feature toggle (feature flag);
  • if feature is disabled, returns HTTP 410 GONE
  • If it's common for many controllers, move the code to controller's base class

The code:

public class TestController : ApiController
{
    public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
    {
        var featureFlag = Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["EnableTest"]);

        if (featureFlag == false)
        {
            return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Gone));
        }

        return base.ExecuteAsync(controllerContext, cancellationToken);
    }
Selah answered 27/3, 2017 at 11:8 Comment(0)
E
0

To remove entire assemblies of controllers might not be a feasible solution. Instead, we can use conventions

create a convention:

public class ControllerDisableConvention : IControllerModelConvention
{
    private readonly Type _controllerType;
    private readonly bool _inherit;
    public ControllerDisableConvention(Type controllerType, bool inherit = true)
    {
        _controllerType = controllerType;
        _inherit = inherit;
    }

    public void Apply(ControllerModel controller)
    {
        if ((!_inherit || !_controllerType.IsAssignableFrom(controller.ControllerType)) && _controllerType != controller.ControllerType)
        {
            return;
        }

        controller.ApiExplorer.IsVisible = false;
        controller.Actions.Clear();
        controller.Selectors.Clear();
        controller.ControllerProperties.Clear();
        controller.Filters.Clear();
        controller.Properties.Clear();
    }
}

usage:

public virtual void ConfigureServices(IServiceCollection services)
{
   ...
   services.AddControllers().AddMvcOptions(opts =>
   {
       if(yourCondition)
          opts.Conventions.Add(new ControllerDisableConvention(typeof(ExampleController));
   });
   ...
}
Expanse answered 5/5 at 14:35 Comment(2)
How does this work ?Zolly
@gobes, when building the services for each type of controller, this convention is tried to be applied if the matched type is found. The controller route, methods, and information are removed and hidden from Api explorer and this checking only happens onceNorling

© 2022 - 2024 — McMap. All rights reserved.