gpt4 book ai didi

httpcontext - 将 HttpContext 添加到 HangFire

转载 作者:行者123 更新时间:2023-12-03 14:39:34 28 4
gpt4 key购买 nike

我是 HangFire 的初学者,期待使用 HangFire 每月在我的网络应用程序中调用一些操作。但是这些操作需要 HttpContext。

那么我的问题是:有没有办法在 HangFire 项目中添加(或创建)一个 httpcontext?

我试图谷歌但没有合适的答案。
谢谢你的帮助!

我找到了一个简短的讨论。很遗憾看到答案是“不可能”。
更新:引用 https://discuss.hangfire.io/t/passing-site-url-to-hangfire-recurrent-jobs/2641

最佳答案

我有一个类似的场景,系统严重依赖 Session,我采用了同样的方法来伪造 HttpContext 并传递 session 变量。

在我的方法中,我收到一个可序列化的上下文,其中包含所有 session 变量:

public static void MyMethod(Hangfire.Server.PerformContext context, Hangfire.IJobCancellationToken cancellationToken, 
SerializeableHttpContext serializeableHttpContext, ... etc)
{
using (var fakeContext = serializeableHttpContext.CreateFakeHttpContext()) {
// ...
}
}

在入队期间,我将当前上下文传递给我的可序列化上下文,它将捕获所有当前变量:

// null and null are injected by Hangfire
Hangfire.BackgroundJob.Enqueue(() => MyMethod(null, null, new SerializeableHttpContext(System.Web.HttpContext.Current), etc..);

这就是魔法发生的地方。这将保存所有 session 变量,并将恢复它们。
请注意,使用 IDispose 很重要,因为您的下一个 Hangfire 作业不想从前一个作业继承假的 HttpContext,因此您需要清理 HttpContext。

/// <summary>
/// This serializes HttpContext with primitive Session variables
/// </summary>
[Serializable]
public class SerializeableHttpContext
{
public Uri RequestUrl { get; set; }
public Dictionary<string, object> SessionVariables { get; set; }

/// <summary>
/// Given a real HttpContext (you can pass System.Web.HttpContext.Current), this saves all useful information
/// into this serializable class, so that you can later reuse (restore) a cloned fake HttpContext
/// </summary>
/// <param name="httpContext">You'll probably want to pass System.Web.HttpContext.Current</param>
public SerializeableHttpContext(HttpContext httpContext)
{
this.RequestUrl = httpContext.Request.Url;

// Save all Session variables
this.SessionVariables = new Dictionary<string, object>();
foreach (object objkey in httpContext.Session.Keys)
{
string key = objkey as string;
if (key == null || httpContext.Session[key] == null)
continue;
Type type = httpContext.Session[key].GetType();

if (type.IsPrimitive || type == typeof(string))
{
try
{
// ignore if not serializable
object val = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(httpContext.Session[key]));
this.SessionVariables.Add(key, httpContext.Session[key]);
}
catch (Exception) { }
}
}

}

/// This is for internal usage, when deserializing.
public SerializeableHttpContext()
{
}

/// <summary>
/// Deserializes into a Fake HttpContext
/// </summary>
/// <returns></returns>
protected HttpContext Deserialize()
{
var httpRequest = new HttpRequest("", this.RequestUrl.AbsoluteUri, "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);

var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
new HttpStaticObjectsCollection(), 10, true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);

httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard,
new[] { typeof(HttpSessionStateContainer) },
null)
.Invoke(new object[] { sessionContainer });

// Restore session variables
if (this.SessionVariables != null)
foreach (string key in this.SessionVariables.Keys)
httpContext.Session[key] = this.SessionVariables[key];

// Restore context variables
if (this.ContextVariables != null)
foreach (string key in this.ContextVariables.Keys)
httpContext.Items[key] = this.ContextVariables[key];

return httpContext;
}

/// <summary>
/// Deserializes this class back into a fake HttpContext, and automatically sets that into System.Web.HttpContext.Current
/// Don't forget to DISPOSE this instance at the end, so that the Context is cleared (else Hangfire will reuse this thread with previous HttpContext)
/// </summary>
public FakeHttpContext CreateFakeHttpContext()
{
return new FakeHttpContext(this.Deserialize());
}

public class FakeHttpContext : IDisposable
{
HttpContext previousContext;
public FakeHttpContext(HttpContext context)
{
previousContext = HttpContext.Current;
HttpContext.Current = context;
}
public void Dispose()
{
HttpContext.Current = previousContext; // previousContext is probably null, but one might be using FakeHttpContexts even inside an existing web context
}
}
}


关于httpcontext - 将 HttpContext 添加到 HangFire,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47404479/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com