Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Session DryIoC/Web API 2/OWIN和会话管理_Session_Asp.net Web Api_Asp.net Web Api2_Owin_Dryioc - Fatal编程技术网

Session DryIoC/Web API 2/OWIN和会话管理

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映射到

试图找出在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将使用它注入控制器

编辑:我试图隐藏所有会话管理样板文件,并向所有控制器注入一个已初始化的会话。如果没有此请求的会话,单独的路由将返回一个错误。另一个需要注意的是,客户端必须显式获取令牌。没有全局令牌的概念“当前”令牌或会话

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;
    }
}