无法在NancyContext中找到OwinContext

时间:2016-05-01 11:53:23

标签: c# owin nancy

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

这个问题触及了这个问题,但其中没有解决方案:Get current owin context in self host mode

它说对于Nancy来说,你必须使用NancyContext来获取Items字典并查找与键相对应的值" OWIN_REQUEST_ENVIRONMENT"。

我可以访问NancyContext,我可以看到Items字典,它包含一个名为" OWIN_REQUEST_ENVIRONMENT"的密钥。 (我也可以调用NancyContext.GetOwinEnvironment()扩展名,这会产生相同的结果 但是,当我获得该密钥时,它不包含实际的IOwinContext。

它包含许多关于Owin信息的键(一些键是 owin.RequestPath owin.RequestMethod owin.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?
    }
}

3 个答案:

答案 0 :(得分:1)

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

    }
}

答案 1 :(得分:0)

实际上,问you mentioned有一些你可能错过的提示。

  

对于Nancy,您必须使用NancyContext来访问Items字典   并查找与该键对应的值   “OWIN_REQUEST_ENVIRONMENT”。对于SignalR,环境属性   IRequest允许您访问OWIN环境。 一旦你有了OWIN   在环境中,您可以使用环境创建一个新的OwinContext。

所以,一旦你调用了var owinEnvironment = Context.GetOwinEnvironment()并获得了字典,那么就可以创建OwinContext(这只是这些字典值的包装)

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

此外,您可以从OwinContext获取HttpContext

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

答案 2 :(得分: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
        }
    }

买者

上面列出的中间件未经测试,因为我的中间件更复杂,我没有时间创建一个工作示例。我找到了关于如何创建Owin中间件on this page的简单概述。