我有一个 ASP.NET Web API (.NET 4) 应用程序,它有几个控制器。我们将在 IIS 上运行几个 Web API 应用程序实例,但有一点不同。在某些 IIS 实例下,只有某些控制器可用。我在想的是在实例启动时禁用/卸载不适用于实例的控制器。
任何人都可以获得一些可以指导我正确方向的信息吗?
我有一个 ASP.NET Web API (.NET 4) 应用程序,它有几个控制器。我们将在 IIS 上运行几个 Web API 应用程序实例,但有一点不同。在某些 IIS 实例下,只有某些控制器可用。我在想的是在实例启动时禁用/卸载不适用于实例的控制器。
任何人都可以获得一些可以指导我正确方向的信息吗?
您可以通过装饰 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());
更新
自从我查看这个问题以来已经有一段时间了,但是如果我今天要解决它,我会稍微改变方法并使用 custom IHttpControllerSelector。这在激活器之前调用,并为启用和禁用控制器提供了一个更有效的位置......(尽管其他方法确实有效)。您应该能够装饰或继承自DefaultHttpControllerSelector.
我认为我不会卸载控制器,而是创建一个自定义 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"]);
    }
    如果您想打开/关闭控制器并具有默认的捕获所有路由控制器,则该IHttpControllerActivator实现不会禁用使用属性 routing 定义的路由。关闭 usingIHttpControllerActivator会禁用控制器,但是当请求路由时,它不会命中所有路由控制器 - 它只是尝试命中已删除的控制器并返回未注册的控制器。