November Happy Hour will be moved to Thursday December 5th.

blob open read issue

Vote:
 

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

#113925
Dec 01, 2014 17:04
Vote:
 

any idea?

#114010
Dec 02, 2014 18:36
Vote:
 

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.

#114136
Dec 04, 2014 19:18
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.