Session DryIoC/Web API 2/OWIN和会话管理
试图找出在VS2015、.Net 4.5上使用DryIoC(v2.0.0-rc4build353)、MS OWIN(v3.0.1、WebAPI2(客户端v5.2.3)建立会话管理的方法 我正在用REST API包装一个相当复杂的遗留应用程序。严格意义上的API服务器,没有UI/MVC。我知道我不可能完全不使用状态,因为我必须保留一个“模型”开放服务器端。用户还必须在模型中进行身份验证。因此出现了会话的概念。我希望尽可能多地使用DI 我第一次放弃的尝试是使用Ninject并将ISession映射到提供者工厂。虽然Ninject有它的优点(例如模块),但我不喜欢它的复杂性。我不知道如何从工厂访问请求对象。经过一些研究,我决定切换到DryIoC 在下面的代码示例中,DryIoC创建了一个单例会话(请参见下面的重用)并将其注入到我的RootController中。如果我在瞬态范围中注册会话,显然每个请求都会得到一个会话。我设想,对(比如)“api/login”的调用将生成一个令牌。客户端将缓存它,并在头中随后续调用一起提交(同时启用API版本控制) 挣扎于如何管理范围界定 编辑:澄清我认为我需要什么:我不确定如何实现DryIoC在实例化控制器之前调用的工厂,在那里我将查找会话令牌并创建/查找关联的ISession实例。然后DryIoC将使用它注入控制器 编辑:我试图隐藏所有会话管理样板文件,并向所有控制器注入一个已初始化的会话。如果没有此请求的会话,单独的路由将返回一个错误。另一个需要注意的是,客户端必须显式获取令牌。没有全局令牌的概念“当前”令牌或会话Session DryIoC/Web API 2/OWIN和会话管理,session,asp.net-web-api,asp.net-web-api2,owin,dryioc,Session,Asp.net Web Api,Asp.net Web Api2,Owin,Dryioc,试图找出在VS2015、.Net 4.5上使用DryIoC(v2.0.0-rc4build353)、MS OWIN(v3.0.1、WebAPI2(客户端v5.2.3)建立会话管理的方法 我正在用REST API包装一个相当复杂的遗留应用程序。严格意义上的API服务器,没有UI/MVC。我知道我不可能完全不使用状态,因为我必须保留一个“模型”开放服务器端。用户还必须在模型中进行身份验证。因此出现了会话的概念。我希望尽可能多地使用DI 我第一次放弃的尝试是使用Ninject并将ISession映射到
using System;
using System.Web.Http;
using Microsoft.Owin.Hosting;
using Microsoft.Owin.Diagnostics;
using Owin;
using DryIoc;
using DryIoc.WebApi;
namespace di_test
{
class Program
{
static void Main(string[] args)
{
var url = "http://localhost:8065";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("Owin host started, any key to exit");
Console.ReadKey();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app_)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "default",
routeTemplate: "{controller}"
);
var di = new DryIoc.Container();
di.Register<ISession, Session>(Reuse.Singleton);
di.WithWebApi(config);
app_.UseWebApi(config);
app_.UseErrorPage(ErrorPageOptions.ShowAll);
}
}
public interface ISession
{
string Token { get; }
}
public class Session : ISession
{
string m_token = null;
public Session()
{
Console.WriteLine("Session()");
}
public string Token => m_token ?? (m_token = Guid.NewGuid().ToString());
}
[RoutePrefix("api")]
public class RootController : ApiController
{
readonly ISession m_session;
public RootController(ISession session_)
{
m_session = session_;
}
[Route()]
public IHttpActionResult GetApiRoot()
{
return Json(
new
{
type = "root",
token = m_session.Token
});
}
}
}
使用系统;
使用System.Web.Http;
使用Microsoft.Owin.Hosting;
使用Microsoft.Owin.Diagnostics;
使用Owin;
使用DryIoc;
使用DryIoc.WebApi;
名称空间di_测试
{
班级计划
{
静态void Main(字符串[]参数)
{
变量url=”http://localhost:8065";
使用(WebApp.Start(url))
{
WriteLine(“Owin主机已启动,任何要退出的键”);
Console.ReadKey();
}
}
}
类启动
{
公共无效配置(IAppBuilder应用程序)
{
var config=新的HttpConfiguration();
config.maphttpAttribute路由();
config.Routes.MapHttpRoute(
名称:“默认”,
routeTemplate:“{controller}”
);
var di=新的DryIoc.Container();
di.寄存器(重用.单例);
di.WithWebApi(配置);
app_u2;UseWebApi(配置);
app.UseErrorPage(ErrorPageOptions.ShowAll);
}
}
公共接口会话
{
字符串标记{get;}
}
公开课:ISession
{
字符串m_token=null;
公开会议()
{
Console.WriteLine(“Session()”);
}
公共字符串标记=>m_标记??(m_标记=Guid.NewGuid().ToString());
}
[RoutePrefix(“api”)]
公共类根控制器:ApiController
{
只读会话m_会话;
公共根控制器(ISession会话)
{
m_session=session_;
}
[路由()]
公共IHttpActionResult GetApiRoot()
{
返回Json(
新的
{
type=“root”,
token=m_session.token
});
}
}
}
如果您只想对这个特定接口执行一次,并且不介意手动管理它的生存期,您可以使用RegisterDelegate创建一个工厂
:
var sessions = new ConcurrentDictionary<Token, Session>();
di.RegisterDelegate<ISession>( _ => {
var token = GetCurrentToken();
return sessions.GetOrAdd( token, t => new Session( t ) );
} );
var sessions=新建ConcurrentDictionary();
di.RegisterDelegate(=>{
var token=GetCurrentToken();
returnsessions.GetOrAdd(token,t=>newsession(t));
} );
或者,如果您想将“每个令牌”的概念应用于广泛的组件,您可以实现一个定制的IReuse
,它可以查找“当前范围”,而“范围”只是实例的缓存
然而,我不推荐这种设计。对于这种逻辑,这是错误的层
举个例子:当没有当前令牌时,你会怎么做?当然,你可以抛出一个异常,但是没有地方可以捕捉到该异常-此时你仍在构建组件图,-因此客户端只会看到WebApi自动生成的异常消息。丑陋。更不用说你没有机会执行任何异常掩盖、记录事件等等
另一个例子:在开发的后期阶段,您很可能希望在构建会话之前使用该令牌做一些事情。比如,验证它,或者检查它是否已过期或已被召回,或者诸如此类。现在您正在向DI连接代码添加更高级别的业务逻辑。丑陋。无法维护
更好的方法是使用名为ISessionManager
的单例组件,然后将其注入控制器,并使用控制器调用ISessionManager.GetCurrentSession()
或其他什么。这样你就不会束缚自己:以后你可以选择扩展GetCurrentSession
的功能,或者你可以选择更改其返回类型以包含可能的错误(例如,“无令牌”、“令牌过期”等),并让控制器向使用者报告
想想看。首先,我不是一个网络维护者(而是DryIoc维护者),我没有完全理解您想要实现的会话管理。但如果您想利用请求实现这一点,您可以
public class Startup
{
public void Configuration(IAppBuilder app_)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "default",
routeTemplate: "{controller}"
);
var di = new DryIoc.Container();
// NOTE: Registers ISession provider to work with injected Request
di.Register<ISession>(Made.Of(() => GetSession(Arg.Of<HttpRequestMessage>())));
di.WithWebApi(config);
app_.UseWebApi(config);
app_.UseErrorPage(ErrorPageOptions.ShowAll);
}
public static ISession GetSession(HttpRequestMessage request)
{
// TODO: This is just a sample. Insert whatever session management logic you need.
var session = new Session();
return session;
}
}