Hi Khurram,
Below is the body of ProcessRequestAsyncInternal() as decompiled from from BlobHttpHandler in EPiServer.dll version 7.17.0.0.
(Hopefully whitespace is preserved.)
// Type: EPiServer.Web.BlobHttpHandler // Assembly: EPiServer, Version=7.17.0.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7 protected virtual IAsyncResult ProcessRequestAsyncInternal(HttpContextWrapper context, AsyncCallback cb, object extraData) { Blob blob = (Blob) null; bool flag = this.ProccessBlobRequest((HttpContextBase) context, out blob); if (blob != null) { context.Response.ContentType = MimeMapping.GetMimeMapping(blob.ID.LocalPath); if (blob is FileBlob) { this.TransmitFile((HttpContextBase) context, ((FileBlob) blob).FilePath); } else { Stream stream = blob.OpenRead(); if (stream.CanSeek) return this.BeginTransmitStream((HttpContextBase) context, stream, (AsyncCallback) (r => this.DisposeOnCallback(r, cb, (IDisposable) stream)), (object) stream); try { this.TransmitStream((HttpContextBase) context, stream); } finally { stream.Dispose(); } } } AsyncResult asyncResult = new AsyncResult(cb, (object) new bool?(flag)); asyncResult.SetCompleted(); return (IAsyncResult) asyncResult; }
You described your memory optimization of OpenRead, nice work! However it returns null.
In the decompiled implementation of ProcessRequestAsyncInternal() above, you can see that the object reference from OpenRead is set to a local variable called "stream".
Subsequently, the CanSeek property is checked. I believe that is what might be causing the exceptions in your log.
One thing you might be able to do in your OpenRead implementation is just construct and return a dummy Stream object with its CanSeek property set to false. This should allow ProcessRequestAsyncInternal() to proceed along its happy path.
Let me know if this works for you.
Apologies to post again as my other question link is breaking....
I have written a custom blob provider to access images stored at cloudinary.
I was using following code in OpenRead function
public override System.IO.Stream OpenRead()
{
string imagePath = this.NoImagePath;
try
{
imagePath = string.Format(this.CloudinaryPath, this.ImageDirectory, this.ImageFile);
WebRequest req = WebRequest.Create(new Uri(imagePath));
WebResponse response = req.GetResponse();
byte[] result = null;
int byteCount = Convert.ToInt32(response.ContentLength);
using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))
{
result = reader.ReadBytes(byteCount);
}
return new MemoryStream(result);
}
catch (Exception ex)
{
Stream fs = File.OpenRead(this.NoImagePath);
return fs;
}
}
If you notic here I was using a Webclient to download image.
I suspected with this techinque I am loading images in my servers memory first and then displaying to client.
so i changed the code FROM
WebRequest req = WebRequest.Create(new Uri(imagePath));
WebResponse response = req.GetResponse();
byte[] result = null;
int byteCount = Convert.ToInt32(response.ContentLength);
using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))
{
result = reader.ReadBytes(byteCount);
}
return new MemoryStream(result);
to
System.Web.HttpContext.Current.Response.Redirect(imagePath, true);
return null;
It works fine for i have one exception recorded on each access.
ERROR EPiServer.Global - 1.2.5 Unhandled exception in ASP.NETSystem.NullReferenceException: Object reference not set to an instance of an object. at EPiServer.Web.BlobHttpHandler.ProcessRequestAsyncInternal(HttpContextWrapper context, AsyncCallback cb, Object extraData) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Is it wrong way to deal with images already stored on Cloudinary's clouds (http://cloudinary.com/) .
How can i fix that exception. Its not showing any runtime error.
You can find previous code here.
http://world.episerver.com/code/K-Khan-/Cloudinary-Implementation-in-Blob/
Regards
Khurram