I have a log running service that creates several thousands of uCommerce products and for most of them it adds a related photo.
I kick off this process using a web service and because the process runs for over one hour the web API call times out after one hour.
To address this I call the long running class using Task.Run so it runs on a separate new thread. This works fine except for if I need to add photos.
Adding Photos as Umbraco Media requires the media service defined as follows
var mediaService = ApplicationContext.Current.Services.MediaService;
BUT then some lines that then use this mediaService cause an exception. Some do not . For example the first line below does not and the second line does.
IMedia ProductImage_StndrdSize = mediaService.CreateMedia(productImage_StndrdSize_FileName, tTImagesFolderID, "Image"); <<<<< This line works
mediaService.Save(ProductImage_StndrdSize); <<<<< This line causes exception
This only happens when running the method on a separate thread.
The exception is
System.ArgumentNullException was unhandled by user code
HResult=-2147467261
Message=Value cannot be null.
Parameter name: httpContext
ParamName=httpContext
Source=System.Web
StackTrace:
at System.Web.HttpContextWrapper..ctor(HttpContext httpContext)
at Umbraco.Web.SingletonHttpContextAccessor.getValue()
at Umbraco.Web.RequestLifespanMessagesFactory.Get()
at Umbraco.Core.Services.MediaService.Umbraco.Core.Services.IMediaServiceOperations.Save(IMedia media, Int32 userId, Boolean raiseEvents)
at Umbraco.Core.Services.MediaService.Save(IMedia media, Int32 userId, Boolean raiseEvents)
at TeraTastic.TTClasses.TTUCommerceAdmin.TTImportData(RequestTTImportData requestTTImportData, String webSiteRootPhysicalPath) in D:\Clancy\ATeraTastic\Dev\TeraTastic14\TeraTastic\TTClasses\TTUCommerceAdmin.cs:line 3474
at TeraTastic.Controllers.TTUCAdminController.<>cDisplayClass120.0() in D:\Clancy\ATeraTastic\Dev\TeraTastic14\TeraTastic\Controllers\TT_UCAdminController.cs:line 441
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
InnerException:
I think the problem is that because I am running the code on a new thread I lose the httpContext I had on the calling thread.
Assuming this to be the problem (let me know if otherwise) my question becomes:
Can I, and how can I, run this code on a hew thread when I don't have httpContext ?
You are right, it's the lack of the underlying HttpContext that causes the issue. I have heard of people faking the context, but not sure if this will work in every instance.
Here's an example of faking it you might be able to try:
Umbraco MediaService on sperate thread generates an Exception
Note this has also been posted at http://eureka.ucommerce.net/#!/question/2157/Problem-adding-thousands-of-uCommerce-products-Umbraco-MediaService-on-sperate-thread-generates-an-Exception#top
Dear Umbraco Folk,
I have a log running service that creates several thousands of uCommerce products and for most of them it adds a related photo.
I kick off this process using a web service and because the process runs for over one hour the web API call times out after one hour.
To address this I call the long running class using Task.Run so it runs on a separate new thread. This works fine except for if I need to add photos.
Adding Photos as Umbraco Media requires the media service defined as follows
var mediaService = ApplicationContext.Current.Services.MediaService;
BUT then some lines that then use this mediaService cause an exception. Some do not . For example the first line below does not and the second line does.
This only happens when running the method on a separate thread.
The exception is
System.ArgumentNullException was unhandled by user code HResult=-2147467261 Message=Value cannot be null. Parameter name: httpContext ParamName=httpContext Source=System.Web StackTrace: at System.Web.HttpContextWrapper..ctor(HttpContext httpContext) at Umbraco.Web.SingletonHttpContextAccessor.getValue() at Umbraco.Web.RequestLifespanMessagesFactory.Get() at Umbraco.Core.Services.MediaService.Umbraco.Core.Services.IMediaServiceOperations.Save(IMedia media, Int32 userId, Boolean raiseEvents) at Umbraco.Core.Services.MediaService.Save(IMedia media, Int32 userId, Boolean raiseEvents) at TeraTastic.TTClasses.TTUCommerceAdmin.TTImportData(RequestTTImportData requestTTImportData, String webSiteRootPhysicalPath) in D:\Clancy\ATeraTastic\Dev\TeraTastic14\TeraTastic\TTClasses\TTUCommerceAdmin.cs:line 3474 at TeraTastic.Controllers.TTUCAdminController.<>cDisplayClass120.0() in D:\Clancy\ATeraTastic\Dev\TeraTastic14\TeraTastic\Controllers\TT_UCAdminController.cs:line 441 at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.Execute() InnerException:
I think the problem is that because I am running the code on a new thread I lose the httpContext I had on the calling thread.
Assuming this to be the problem (let me know if otherwise) my question becomes:
Can I, and how can I, run this code on a hew thread when I don't have httpContext ?
Terry Clancy
ClanceZ
You are right, it's the lack of the underlying HttpContext that causes the issue. I have heard of people faking the context, but not sure if this will work in every instance.
Here's an example of faking it you might be able to try:
https://gist.github.com/sniffdk/7600822
Thank you Dan,
The solution you suggested did not fix the problem, probably because it fakes UmbracoContext rather than httpContext.
I did however solve my problem by Faking httpContext based on code from http://stackoverflow.com/questions/28085439/parameter-cannot-be-null-parameter-name-http-context
Here is my (very similar) code:
The Helper Class
and here is how you use it. In my case I put this are the beginning of the Method I call as a new thread:
I actually think this is a kind of ugly solution. If anyone has a better approach let me know !!
Otherwise, I hope this helps folk :-)
Terry Clancy
ClanceZ
is working on a reply...