从服务调用MVC UrlHelper

本文关键字:UrlHelper MVC 调用 服务 | 更新日期: 2023-09-27 18:27:07

我有一个静态类,它发送带有指向我的网站某些页面链接的电子邮件。这个链接是用这个代码动态生成的:

UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
string url = urlHelper.Action("Details", "Product", new { id = ticketId }, "http");

问题是,我现在还有一个服务,它定期比较创建日期和当前日期,并自动发送这些邮件。代码当然崩溃了,并说HttpContext.Current为null(因为它不是一个请求)。

我试过一些类似的东西:

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引用异常。

在通过服务调用邮件方法时,我未能以某种方式保存/记住/传递UrlHelper或HttpContext以获得访问权限。

从服务调用MVC UrlHelper

感谢您的帮助。在我的情况下,预定义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);
}

解释发生了什么:对于每个请求,都会使用Initialize方法调用FirstRequestInitialization类,并将上下文作为参数。这从来都不是问题,因为上下文在Application_BeginRequest中是已知的(不像Application_Start中那样)。Initialize方法注意线程仍然只被调用一次,并且有一个锁,这样它就永远不会崩溃。我取消了我的服务,因为我不能真正与它通信,相反,我决定用它创建一个线程。在这个Initialize方法中,我调用了一个类构造函数EscalationThread,并将主机作为参数。在这个构造函数中,我创建并启动了保持运行的线程。

我仍然没有HttpContext,也不能使用UrlHelper,但我有主机,可以做一些事情,比如:string urlInMail = this.host + string.Format("/{0}/{1}/{2}", "Product", "Details", product.Id);