在运行时禁用ApiController

时间:2012-11-21 01:02:01

标签: asp.net-web-api

我有一个ASP.NET Web API(.NET 4)应用程序,它有一些控制器。我们将在IIS上运行Web API应用程序的多个实例,但有一点不同。某些IIS实例下只能使用某些控制器。我想的是在实例启动时禁用/卸载不适用于实例的控制器。

任何人都能获得一些可以指导我正确方向的信息吗?

3 个答案:

答案 0 :(得分:3)

我认为不是卸载控制器,而是创建一个自定义的Authorize属性,在决定授权时查看实例信息。

您可以在类级别向每个控制器添加以下内容,也可以将其添加到各个控制器操作中:

[ControllerAuthorize (AuthorizedUserSources = new[] { "IISInstance1","IISInstance2","..." })]

以下是属性的代码:

public class ControllerAuthorize : AuthorizeAttribute
{
    public ControllerAuthorize()
    {
        UnauthorizedAccessMessage = "You do not have the required access to view this content.";
    }

    //Property to allow array instead of single string.
    private string[] _authorizedSources;

    public string UnauthorizedAccessMessage { get; set; }

    public string[] AuthorizedSources
    {
        get { return _authorizedSources ?? new string[0]; }
        set { _authorizedSources = value; }
    }

    // return true if the IIS instance ID matches any of the AllowedSources.
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException("httpContext");

        //If no sources are supplied then return true, assuming none means any.
        if (!AuthorizedSources.Any())
            return true;

        return AuthorizedSources.Any(ut => ut == httpContext.ApplicationInstance.Request.ServerVariables["INSTANCE_ID"]);
    }

答案 1 :(得分:3)

您可以通过装饰DefaultHttpControllerActivator来放置自己的自定义IHttpControllerActivator。在内部只检查设置,只在允许的情况下创建控制器。

当您从Create方法返回null时,用户将收到404 Not Found消息。

我的示例显示正在检查应用程序设置(App.Config或Web.Config)中的值,但显然这可能是任何其他环境感知条件。

public class YourCustomControllerActivator : IHttpControllerActivator
{
    private readonly IHttpControllerActivator _default = new DefaultHttpControllerActivator();

    public YourCustomControllerActivator()
    {

    }

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor,
                                  Type controllerType)
    {
        if (ConfigurationManager.AppSettings["MySetting"] == "Off")
        {
            //Or get clever and look for attributes on the controller in controllerDescriptor.GetCustomAttributes<>(); 
            //Or use the contoller name controllerDescriptor.ControllerName
            //This example uses the type
            if (controllerType == typeof (MyController) ||
                controllerType == typeof (EtcController))
            {
                return null;
            }
        }
        return _default.Create(request, controllerDescriptor, controllerType);

    }
}   

您可以像这样切换激活器:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new YourCustomControllerActivator());

<强>更新

自从我查看这个问题已经有一段时间了,但如果我今天要解决这个问题,我会稍微改变一下这个方法并使用自定义IHttpControllerSelector。这在激活器之前被调用,并且使得启用和禁用控制器的位置稍微更有效......(尽管另一种方法确实有效)。您应该能够装饰或继承DefaultHttpControllerSelector

答案 2 :(得分:0)

IHttpControllerActivator实现不会禁用使用属性路由定义的路由,如果要打开/关闭控制器并使用默认捕获所有路由控制器。使用IHttpControllerActivator关闭会禁用控制器,但是当请求路由时,它不会捕获所有路由控制器 - 只是尝试命中已删除的控制器并且不返回已注册的控制器。