2016-05-01 46 views
2

我有一个使用Nancy的自我托管的Owin应用程序。在其中一个NancyModules中,我需要获得IOwinContext的实例。在NancyContext中找不到OwinContext

这个问题倒是主题,但在它没有解决:Get current owin context in self host mode

它说,南希,你必须使用NancyContext去的项目字典,并寻找相应的键“的价值OWIN_REQUEST_ENVIRONMENT”。

我确实可以访问NancyContext,我可以看到Items字典并且它包含一个名为“OWIN_REQUEST_ENVIRONMENT”的键。 (我也可以拨打NancyContext.GetOwinEnvironment()扩展,可以得到相同的结果 然而,当我拿到钥匙不包含实际IOwinContext。

它含有大量键约Owin(某些按键信息是owin.RequestPathowin.RequestMethodowin.CallCancelled,更多),但不是实际的上下文对象。它是唯一真正有各种键一本字典,所以我不能将其转换为IOwinContext

如何从NancyContext获得IOwinContext对象?


public class MyStartup 
{ 
    public void Start() 
    { 
     var options = new StartOptions() 
     options.Urls.Add(new Uri("http://*:8084")); 
     options.AppStartup(this.GetType().AssemblyQualifiedName; 
     var host = WebApp.Start(options, Configuration); 
    } 

    public void Configuration(IAppBuilder app) 
    { 
     app.UseNancy(); 
    } 
} 

public class MyModule : NancyModule 
{ 
    Get["/", true] = async(x, ct) => 
    { 
     var owinEnvironment = Context.GetOwinEnvironment(); 
     // Now what? 
    } 
} 

回答

0

我结束了创建新Owin中间件解决这一点。在中间件中,您可以访问当前的Owin上下文,从而可以访问Owin环境。

当您有权访问Owin环境时,只需将Owin上下文添加到环境中即可。当环境处于环境中时,您可以在NancyModule中检索它。

在像这样获取它之后,我也可以访问上下文中的GetUserManager()方法,这样我就可以获得我的AspNetIdentity管理器(正如我在另一个答案的评论中提到的那样)。请记住,必须在Nancy之前将中间件添加到Owin管道中。

启动

public class Startup 
{ 
    public void Start() 
    { 
     var options = new StartOptions() 
     options.Urls.Add(new Uri("http://*:8084")); 
     options.AppStartup(this.GetType().AssemblyQualifiedName; 
     var host = WebApp.Start(options, Configuration); 
    } 

    public void Configuration(IAppBuilder app) 
    { 
     app.Use(typeof(OwinContextMiddleware)); 
     app.UseNancy(); 
    } 
} 

中间件

public class OwinContextMiddleware : OwinMiddleware 
{ 
    public OwinContextMiddleware(OwinMiddleware next) 
     : base(next) 
    { 
    } 

    public async override Task Invoke(IOwinContext context) 
    { 
     context.Environment.Add("Context", context); 
     await Next.Invoke(context); 
    } 
} 

NancyModule

public class MyModule : NancyModule 
{ 
    public MyModule() 
    { 
     Get["/", true] = async(x, ct) => 
     { 
      IDictionary<string, object> environment = Context.GetOwinEnvironment(); 
      IOwinContext context = (IOwinContext)environment["Context"]; // The same "Context" as added in the Middleware 
     } 
    } 

洞at

上面列出的中间件没有经过测试,因为我拥有的中间件比较复杂,我没有时间去创建一个工作示例。我发现如何创建Owin中间件on this page的简单概述。

0

其实,疑问,you mentioned有一些提示,你可能错过了。

南希,你必须使用NancyContext去的项目字典 并查找对应的键 “OWIN_REQUEST_ENVIRONMENT”的值。对于SignalR, 的环境属性IRequest使您可以访问OWIN环境。 一旦拥有OWIN 环境,您就可以使用该环境创建一个新的OwinContext。

所以,一旦你叫var owinEnvironment = Context.GetOwinEnvironment()并得到了词典,那么你可以创建OwinContext(这是刚刚包装器,这些字典值)

它有一个构造函数OwinContext(IDictionary<String, Object>)它,我想,是你所需要的。

此外,还可以从HttpContext得到OwinContext

// get owin context 
var owinContext = HttpContext.Current.GetOwinContext(); 
// get user manager 
var userManager = owinContext.GetUserManager<YourUserManager>(); 
+0

这个工作在一定程度上,但我似乎无法得到已在较早的时机已经登记的OwinContext,像AspNet.Identity.UserManager对象。在'Configuration(IAppBuilder应用程序)'方法中,我也做了一个'app.CreatePerOwinContext (MyUserManager.Create);'。在创建一个像你所建议的新的OwinContext之后,对'owinContext.GetUserManager ()'的调用返回NULL,所以我不确定创建一个新的OwinContext实际上包含了之前已经注册过的内容。 – GTHvidsten

+0

那么,我相信你可以从基本的http上下文访问owin上下文(我举了一个例子) – MaKCbIMKo

+0

我喜欢使用'HttpContext.Current'的建议,但不幸的是,这从NancyModule类是不可用的。至少在我调试入口点时看到有什么可用。 – GTHvidsten

0
var owinContext = new OwinContext(Context.GetOwinEnvironment()); 

例如:

public class SecurityApi : NancyModule 
{ 
    public SecurityApi() 
    { 
     Post["api/admin/register", true] = async (_, ct) => 
     { 
      var body = this.Bind<RegisterUserBody>(); 

      var owinContext = new OwinContext(Context.GetOwinEnvironment()); 
      var userManager = owinContext.GetUserManager<ApplicationUserManager>(); 

      var user = new User {Id = Guid.NewGuid().ToString(), UserName = body.UserName, Email = body.Email}; 

      var result = await userManager.CreateAsync(user, body.Password); 

      if (!result.Succeeded) 
      { 
       return this.BadRequest(string.Join(Environment.NewLine, result.Errors)); 
      } 

      return HttpStatusCode.OK; 
     }; 

    } 
}