Frage

I have a static class that sends emails with links to certain pages of my site. That link is getting dynamically generated with this code:

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

The problem is I now also have a service that periodically compares the creation date with the current date and sends those mails automatically. The code crashes of course and says HttpContext.Current is null (because it ain't a request).

I tried some things like that:

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

But when I need RequestContext the second time for the UrlHelper.Action crashes saying Null Reference Exception.

I failed to somehow save/remember/pass the UrlHelper or the HttpContext to have access when calling the mail method over my service.

War es hilfreich?

Lösung

Thanks for all your help. Predefining the URL was no option in my case. I found more or less a solution for my problem. I know it might not be the most beautiful code but it works quite well and noone seems to have a better one, so no downvotes please.

In global.asax.cs I added this class:

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

And I added this:

void Application_BeginRequest(Object source, EventArgs e)
{
    FirstRequestInitialisation.Initialise(((HttpApplication)source).Context);
}

Explaination what happens: On each and every request the FirstRequestInitialisation class gets called with the method Initialise with the context as parameter. This is never a problem because the context is known in a Application_BeginRequest (not like in Application_Start). The Initialise Method takes care that still the Thread is just called once and has a lock so that it will never crash. I eliminated my Service because I can't really communicate with it and instead I decided to make a Thread out of it. In this Initialise Method I call a class constructor EscalationThread with the host as parameter. In this constructor I create and start the thread that just keeps running.

I still don't have HttpContext and can't use the UrlHelper BUT I have the host and can do stuff like: string urlInMail = this.host + string.Format("/{0}/{1}/{2}", "Product", "Details", product.Id);

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top