在运行时为Web Api控制器创建资源

时间:2015-09-28 18:03:48

标签: c# asp.net asp.net-web-api2

我的应用程序现在是多租户,我有一个类,根据登录的租户查找要使用的设置。所以我在每个控制器中都有一些基本上看起来像这样的代码。

[RoutePrefix("api/client/{id})]
public class ReportsController : ApiController
{
    ILogHandler _logHandler = new LogHandler();
    private processor _processor = null;

    public ReportsController(IProcessor Processor)
    {
        _processor = Processor;
    }

    [Route("")]
    [HttpGet]
    [EnableQuery]
    public IHttpActionResult Get(Guid id)
    {
            //Some pseudo code here to get some settings for a client
            var settings = clientSettings(id);

            //investigate the settings
            if(settings.CanDoSomething())
                var qi = _processor.process();
            return Ok(qi);
    }
}

我查找一些设置并决定做一些事情。我的问题是每个控制器都必须执行查找过程,但我想要做的是将对象放在那里并确定范围到正确的客户端。

我尝试使用Owin中间件并将对象放在Owin环境中,但我想这是在管道的早期,我不知道Id在中间件中的价值是什么。

我也有autofac,我已经研究过使用multitenant,但这似乎更倾向于解决每个租户的特定依赖关系或让租户访问某些控制器。我所追求的是每个租户每次请求都会获得其中一个对象,但它只需要不同的设置。

1 个答案:

答案 0 :(得分:0)

看起来您已尝试使用Owin Middleware实现此功能。我认为它会起作用,但也许你正在寻找一种简单的方法来获得id字段,这是不可能的。 Owin中间件的问题在于它的工作水平非常低:你只得到一个IDictionary<string, object>,其中包含你需要做的所有信息(在你的情况下,从查询中获取id字符串;在Web Api的情况下,得到一大堆东西)。对此的一个小抽象是OwinMiddleware类;它在类型为IOwinContext的对象中显示来自Web请求的信息。使用Autofac,您可以使用它注册中间件,以便它可以将依赖项注入其中。根据这些信息,我们可以创建一个owin中间件,从查询字符串中抓取id并在注入的ClientSettings实例上设置它:

public class IDParserMiddleware : OwinMiddleware
{
    private ClientSettings Settings;

    public IDParserMiddleware(OwinMiddleware next, ClientSettings settings)
        : base(next)
    {
        Settings = settings;
    }

    public override Task Invoke(IOwinContext context)
    {
        string[] query = context.Request.QueryString.Value.Split('&');
        string id = null;
        foreach (string keyvalue in query)
        {
            if (keyvalue.StartsWith("id=", StringComparison.InvariantCultureIgnoreCase))
            {
                id = keyvalue.Substring(3); // right after "id="
                break;
            }
        }

        Settings.ID = Guid.Parse(id);

        return this.Next.Invoke(context);
    }
}

然后你可以像Owin一样注册这个:

IAppBuilder app; // you get this from Owin code like WebApp.Start()
var builder = new ContainerBuilder();
builder.RegisterType<IDParserMiddleware>();
//...
var container = builder.Build();

// This will add the Autofac middleware as well as the middleware
// registered in the container, like IDParserMiddleware
app.UseAutofacMiddleware(container);
// Finally, register Web Api. We do this last so that our middleware
// can run before it and set the ID property.
app.UseAutofacWebApi(config);
app.UseWebApi(config);

有关这方面的更多信息,请参见this Autofac doc

最后,你可以将ClientSettings注入你的控制器(或任何类的)构造函数中:

public ReportsController(IProcessor Processor, ClientSettings settings)
{
    _processor = Processor;
    _settings = settings;
}

请注意,我没有尝试过这个,但从我读过的内容来看,这应该可行。祝你好运!