我有一个静态类,可以发送带有指向我网站某些页面的链接的电子邮件。该链接通过以下代码动态生成:
UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
string url = urlHelper.Action("Details", "Product", new { id = ticketId }, "http");
问题是我现在还有一项服务,定期将创建日期与当前日期进行比较,并自动发送这些邮件。代码崩溃当然会说HttpContext.Current
为空(因为它不是请求)。
我尝试了类似的东西:
private static System.Web.Routing.RequestContext requestContext;
private static System.Web.Routing.RequestContext RequestContext {
get
{
if(requestContext == null)
requestContext = HttpContext.Current.Request.RequestContext;
return requestContext;
}
}
但是当我需要RequestContext时,UrlHelper.Action第二次崩溃,说Null Reference Exception。
我无法以某种方式保存/记住/传递UrlHelper或HttpContext,以便在通过我的服务调用邮件方法时具有访问权限。
答案 0 :(得分:1)
感谢您的帮助。在我的情况下,预定义URL不是选项。我发现或多或少解决了我的问题。我知道它可能不是最漂亮的代码,但是效果很好而且没有人似乎有更好的代码,所以请不要掉头。
在 global.asax.cs 中我添加了这个类:
class FirstRequestInitialisation
{
private static string host = null;
private static Object s_lock = new Object();
// Initialise only on the first request
public static void Initialise(HttpContext context)
{
if (string.IsNullOrEmpty(host))
{ //host isn't set so this is first request
lock (s_lock)
{ //no race condition
if (string.IsNullOrEmpty(host))
{
Uri uri = HttpContext.Current.Request.Url;
host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;
//open EscalationThread class constructor that starts anonymous thread that keeps running.
//Constructor saves host into a property to remember and use it.
EscalationThread et = new EscalationThread(host);
}
}
}
}
}
我补充说:
void Application_BeginRequest(Object source, EventArgs e)
{
FirstRequestInitialisation.Initialise(((HttpApplication)source).Context);
}
解释会发生什么:在每个请求中,使用方法Initialise以上下文作为参数调用FirstRequestInitialisation类。这绝不是问题,因为Application_BeginRequest中已知上下文(不像Application_Start中那样)。初始化方法需要注意的是,Thread只调用一次并具有锁定,以便它永远不会崩溃。 我取消了我的服务,因为我无法真正与它沟通,而是我决定制作一个线程。在这个Initialise方法中,我使用host作为参数调用类构造函数EscalationThread。在这个构造函数中,我创建并启动了一直运行的线程。
我仍然没有HttpContext但不能使用UrlHelper但是我有主机并可以执行以下操作:string urlInMail = this.host + string.Format("/{0}/{1}/{2}", "Product", "Details", product.Id);