Issue on Orchard 1.4 with Azure using Image Field (Media Picker Field)

Topics: Administration, Customizing Orchard, Troubleshooting
Mar 18, 2012 at 4:55 PM

Hi,

I'm start using Orchard 1.4 on Azure and want now using a Image (Media Picker Field) inside a Content Type.

I can sucessfully upload the Image to the Media Library.

But if I select the Image it add the following URL to the field:  ~/ttps://sample.blob.core.windows.net/media/Default/sample.png

and don't allow to save it.

Any Tips are helpfull.

 

Apr 1, 2012 at 10:44 PM

Has there been any updates to this issue?  I'm also having the same problem.

Coordinator
Apr 2, 2012 at 4:00 AM

What happens when you try to save?

May 9, 2012 at 10:14 PM

I wanted to add to this conversation as there is an issue. An example of this is when you try using the Featured Items rotator module (which utilizes the Media Picker field).  Bertrand, to answer your question, it will not allow you to save as it is an invalid path.  I have looked at the source code and the javascript where the logic is being done to determine whether or not to append an '~/' before the url is done in the MediaPicker.Edit.cshtml.  The full path is: \Modules\Orchard.Fields\Views\EditorTemplates\Fields\MediaPicker.Edit.cshtml.  Here is the section of code that is not being interpreted right:

                var applicationPath = '@Url.RequestContext.HttpContext.Request.ApplicationPath.ToLower()';
                if (!/\/$/.test(applicationPath)) {
                    applicationPath += '/';
                }

                var url = data.img.src.substr(applicationPath.length);

                if (url.substr(4) != "http") {
                    url = '~/' + url;
                }

The C# segment of @Url.RequestContext.HttpContext.Request.ApplicationPath.ToLower() always returns '/'.  As such, the length is 1.  Therefore, the img.src is losing the first character (h) and does not match "http" when the comparison is done.

I believe I understand the value of Request.ApplicationPath (i.e. to determine the virtual path of the application) so I don't want to remove the logic as it would have needs for some users.  I think though, that the code change that should be made that will work for everyone is the following:

                var imgSrc = data.img.src;
                var url
                if (imgSrc.substr(4) != "http") {
                    url = '~/' + imgSrc.substr(applicationPath.length);
                }
                else {
                    url = imgSrc;
                }

This technique simply first checks for "http" prior to extracting the substring (if it doesn't exist).  I think this works for everyone - anyone see where it would cause an issue?

Coordinator
May 9, 2012 at 11:13 PM

It should have been fixed with 1.4.1, could you check ?

May 9, 2012 at 11:51 PM

I utilize the source code and am on Revision 6149 (labeled Branch 1.4.x in TortoiseHg) so I am suspecting I am past 1.4.1.  Is there a better way I can tell?

Coordinator
May 10, 2012 at 12:18 AM

Seems you are right ... the fix I did was not fixing the issue actually ...

Could you try instead with this one ?

                var url = data.img.src;

                if (url.substr(4) != "http") {
                    url = '~/' + url.substr(applicationPath.length);
                }

It should do the same as your code, with less.

May 10, 2012 at 1:28 AM

Yup, you have shown me up :) Your code is definitely more efficient.  I am sure that will work and will only reply back if I have any trouble (will be redeploying tomorrow).

May 10, 2012 at 1:36 AM

Wait, I had to talk to soon.  I think we both have the use of .substr wrong - must be late.  I think what we are actually looking for is url.substr(0, 4).  In other words, start at index 0 and take first four characters.  Ugh.  Here is what I believe we need:

                var url = data.img.src;

                if (url.substr(0, 4) != "http") {
                    url = '~/' + url.substr(applicationPath.length);
                }

Sorry I missed that, I will actually upload it tonight/tomorrow and confirm with you it works.  I will also confirm it works on my localhost (which is equivalent to a non-Azure environment).  I will be back in touch.

 

May 10, 2012 at 2:29 PM

Final confirmation, the final code segment above works perfectly.

May 10, 2012 at 4:24 PM
Edited May 10, 2012 at 4:24 PM

Hello sebastienros,

I have located another one that could use (I feel) correction.  This one comes from using the Media Picker from TinyMCE.  Here is the documentation on how the file is saved in a "bad" path:

Let's say I have a ContentType called "BlogPost" and I have a slug called "/media-articles".  With this combination, in the html on the page I would see the following:

<fieldset>
    <label>Body</label>
    <textarea class="html tinymce" cols="80" data-mediapicker-title="Insert/Update Media" data-mediapicker-uploadpath="BlogPost//media-articles" id="Body_Text" name="Body.Text" rows="25" style="width:100%">
</textarea>

The issue here is the "data-mediapicker-uploadpath" as it should be "BlogPost/media-articles" rather than "BlogPost//media-articles".  The double slash causes the resulting images to be uploaded into a bad folder structure (i.e. a folder with no name that is not browsable through the UI).

I went ahead and analyzed the problem in the code and the issue starts from Orchard.Core.Common.Drivers.BodyPartDriver on line 80:

AddMediaPath = new PathBuilder(part,requestContext).AddContentType().AddContainerSlug().ToString()

The actual issue comes in on the "AddContainerSlug() portion:

public PathBuilder AddContainerSlug() {
	var common = _content.As<ICommonPart>();
	if (common == null || common.Container==null)
		return this;
	var helper = new UrlHelper(_requestContext);
	Add(helper.ItemDisplayUrl(common.Container));
	return this;
}

The line that is problematic is actually the "helper.ItemDisplayUrl(common.Container)" (which is passed into the Add method.  The issues is that it returns "/media-articles" (note that it already has a slash).  This then goes into the "Add" method as seen here:

private void Add(string segment) {
	if (string.IsNullOrEmpty(segment))
		return;
	if (string.IsNullOrEmpty(_path))
		_path = segment;
	else
		_path = _path + "/" + segment;
}

So what you end up getting is the "else" clause which takes and prepends a "/" onto the passed in segment resulting in "BlogPost//media-articles".  My recommendation is that the "Add" method be modified to this:

private void Add(string segment) {
	if (string.IsNullOrEmpty(segment))
		return;
	if (string.IsNullOrEmpty(_path))
		_path = segment;
	else if (segment.StartsWith("/")) {
		_path = _path + segment;
	}
	else {
		_path = _path + "/" + segment;
	}
}

I have tested this and it works (but perhaps there is a better way). I welcome your comments (and will also reference this in the bug request area).