views:

25

answers:

2

My application sends out some emails, and the image paths referenced in the e-mails need to vary depending on how the user accessed the page that is sending the email. I've used variations of the code before many times with no problem, but this is the first time I'm trying to do it in an MVC app:

var relImagePath = controllerContext.HttpContext.Response.ApplyAppPathModifier("~/Emails/Images");
var absImagePath = new Uri(controllerContext.HttpContext.Request.Url, relImagePath).AbsoluteUri;

The second line is throwing an NullReferenceException because HttpContext.Request.Url is null. How can that be?

Edit: I should note that I'm running this code in a thread pool thread separate from the one that processed the request. If I move this code back onto the thread executing the controller action, the url is there. For now, I've resorted to executing the code on the same thread.

A: 

I would suppose that RequestContext grabs current HttpContext at the time you call controllerContext.HttpContext (since it asks RequestContext for the HttpContext), and I suppose that it may just ask HttpContext.Current, and that's why get null.

Try to grab controllerContext.HttpContext in the ASP.NET thread, save it and pass to your own thread, instead of controller context which asks for HttpContext at wrong time later.

That's my guess.

Also, http://csharpfeeds.com/post/5415/Dont_use_the_ThreadPool_in_ASP.NET.aspx

queen3
I suspect you're right about the timing of when the HttpContext is obtained. I'll look into that. However, I also wanted to comment on the article you linked to say that I strongly disagree with its' overall sentiment. Using the thread pool for long running tasks might be a sure fire way to bog down the ASP.NET worker queue, but for numerous short lived "fire and forget" type tasks, the thread pool is the perfect tool, and creating an unbounded number of other threads is almost never a good idea.
Chris
A: 

The HttpContext might not always be accessible in threads. You will need to pass the required information to the thread:

var relImagePath = controllerContext.HttpContext.Response.ApplyAppPathModifier("~/Emails/Images");
var absImagePath = new Uri(controllerContext.HttpContext.Request.Url, relImagePath).AbsoluteUri;
new Thread(state => 
{  
    var imagePath = (string)state;
    // TODO ...
}).Start(absImagePath);

or if you are using the ThreadPool (only for short running tasks):

ThreadPool.QueueUserWorkItem(state => 
{  
    var imagePath = (string)state;
    // TODO ...
}, absImagePath);
Darin Dimitrov