Lee Kelleher’s Weblog

random posts on code, .NET, Umbraco and WordPress

Posts Tagged ‘snippet

How to use umbraco.library GetMedia in XSLT for Umbraco v4.5

with 5 comments

This is a quick follow-up on my previous blog post: “How to use umbraco.library GetMedia in XSLT“.  At the request of fellow Umbraco South-West UK developer, Dan, that I should update the code snippets for the new XML schema in Umbraco v4.5+

First a quick notice; if you are using v4.5.0, then please upgrade to v4.5.1, as there was a tiny bug in GetMedia that caused great confusion and headaches – you have been advised!

Without further ado, the updated XSLT snippet that you came here for…

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/mediaId)" />
	<xsl:if test="$mediaId > 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="$mediaNode/umbracoFile">
			<img src="{$mediaNode/umbracoFile}" alt="[image]" height="{umbracoHeight}" width="{umbracoWidth}" />
		</xsl:if>
	</xsl:if>
</xsl:template>

Any questions? Come join us over at Our Umbraco… we are a friendly bunch!

Written by Lee Kelleher

August 11, 2010 at 3:42 pm

Posted in blog

Tagged with , , , ,

How to use umbraco.library GetMedia in XSLT

with 12 comments

From time to time I notice a reoccurring post over at the Our Umbraco forum; how to display an image (from the Media section) in XSLT?

A quick answer can be found on the Our Umbraco wiki for the umbraco.library GetMedia method.

For most uses, the last example in the wiki works great.  But I want to show you a “super safe” way of dealing with GetMedia in XSLT.

Where I find a lot of the examples go wrong is that they make the assumption that a media node (XML) is returned from the GetMedia call, e.g.

<xsl:value-of select="umbraco.library:GetMedia($currentPage/data[@alias='mediaId'], 'false')/data[@alias='umbracoFile']" />

If the ‘mediaId’ property didn’t contain either a numeric value or a valid media node id, then it would return null … meaning that the following “/data” would throw an Exception! (Displaying “Error parsing XSLT file” message on the front-end.)  Not what you or your users want to see!

In order to consider any user inputs, like media IDs not being selected, or even a referenced media node is deleted in the back-office, here is the “super safe” approach:

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/data[@alias='mediaId'])" />
	<xsl:if test="$mediaId &gt; 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="count($mediaNode/data) &gt; 0">
			<xsl:if test="string($mediaNode/data[@alias='umbracoFile']) != ''">
				<img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]">
					<xsl:if test="string($mediaNode/data[@alias='umbracoHeight']) != ''">
						<xsl:attribute name="height">
							<xsl:value-of select="$mediaNode/data[@alias='umbracoHeight']" />
						</xsl:attribute>
					</xsl:if>
					<xsl:if test="string($mediaNode/data[@alias='umbracoWidth']) != ''">
						<xsl:attribute name="width">
							<xsl:value-of select="$mediaNode/data[@alias='umbracoWidth']" />
						</xsl:attribute>
					</xsl:if>
				</img>
			</xsl:if>
		</xsl:if>
	</xsl:if>
</xsl:template>

Here’s what happens:

  1. The “mediaId” is pulled from a property of the “currentPage” and cast as a number.  Optionally the “mediaId” could be passed in via a macro parameter, or somewhere else?
  2. The first condition checks the the “mediaId” is numeric, and greater-than zero.
  3. The “mediaId” is passed through to “GetMedia”, along with the false flag to only pull-back the required node (not it’s children, for Folder media items).
  4. We check if the media node has any child “data” elements – which contain the data about the image/media.
  5. Then we check if the “umbracoFile” property has any data – if not, then there is no point displaying an image.
  6. There are extra conditions for the “height” and “width” properties – these are optional.

Personally, I add an “altText” property to the Image media-type … and use that in the XSLT – again this is optional, but strongly recommended!

I can see how this “super safe” approach is overkill – especially compared with a single line of XSLT … but from my experience, it’s better to be safe than sorry – especially when dealing with user data-input – your assumptions and expectations of how users will use the system aren’t always correct!

Update: OK, I agree the extra “if” statements are overkill… so here’s a condensed version – assuming that the “umbracoHeight” and “umbracoWidth” properties are always there…

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/data[@alias='mediaId'])" />
	<xsl:if test="$mediaId &gt; 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="count($mediaNode/data) &gt; 0 and string($mediaNode/data[@alias='umbracoFile']) != ''">
			<img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]" height="{$mediaNode/data[@alias='umbracoHeight']}" width="{$mediaNode/data[@alias='umbracoWidth']}" />
		</xsl:if>
	</xsl:if>
</xsl:template> 

Written by Lee Kelleher

November 30, 2009 at 2:33 pm

Posted in blog

Tagged with , , , ,

How to convert NameValueCollection to a (Query) String [Revised]

with 2 comments

Following on from a comment on my previous post about converting a NameValueCollection to a (query) string – I have finally got around to revising my code snippet.  Now the method will handle same key multiple values, (it no longer comma-separates them).

I have also added extra parameters so that you can define your own delimiter (since the HTTP specification says that you can use both ampersands & and semicolons ;) and there is an option for omitting keys with empty values.

/// <summary>
/// Constructs a NameValueCollection into a query string.
/// </summary>
/// <remarks>Consider this method to be the opposite of "System.Web.HttpUtility.ParseQueryString"</remarks>
/// <param name="parameters">The NameValueCollection</param>
/// <param name="delimiter">The String to delimit the key/value pairs</param>
/// <returns>A key/value structured query string, delimited by the specified String</returns>
public static String ConstructQueryString(NameValueCollection parameters, String delimiter, Boolean omitEmpty)
{
	if (String.IsNullOrEmpty(delimiter))
		delimiter = "&";

	Char equals = '=';
	List<String> items = new List<String>();

	for (int i = 0; i < parameters.Count; i++)
	{
		foreach (String value in parameters.GetValues(i))
		{
			Boolean addValue = (omitEmpty) ? !String.IsNullOrEmpty(value) : true;
			if (addValue)
				items.Add(String.Concat(parameters.GetKey(i), equals, HttpUtility.UrlEncode(value)));
		}
	}

	return String.Join(delimiter, items.ToArray());
}

Written by Lee Kelleher

September 19, 2009 at 11:08 pm

Posted in blog

Tagged with , , , , ,

How to convert NameValueCollection to a (Query) String

with 12 comments

Most ASP.NET developers know that you can get a key/value pair string from the Request.QueryString object (via the .ToString() method). However that functionality isn’t the same for a generic NameValueCollection object (of which Request.QueryString is derived from).

So how do you take a NameValueCollection object and get a nicely formatted key/value pair string? (i.e. “key1=value1&key2=value2“) … Here’s a method I wrote a while ago:

/// <summary>
/// Constructs a QueryString (string).
/// Consider this method to be the opposite of "System.Web.HttpUtility.ParseQueryString"
/// </summary>
/// <param name="nvc">NameValueCollection</param>
/// <returns>String</returns>
public static String ConstructQueryString(NameValueCollection parameters)
{
	List<String> items = new List<String>();

	foreach (String name in parameters)
		items.Add(String.Concat(name, "=", System.Web.HttpUtility.UrlEncode(parameters[name])));

	return String.Join("&", items.ToArray());
}

Just in case you didn’t know about the System.Web.HttpUtility.ParseQueryString method, it’s a quick way of converting a query (key/value pairs) string back into a NameValueCollection.

Written by Lee Kelleher

June 6, 2008 at 1:22 pm

Posted in blog

Tagged with , , , ,

Making Request.QueryString writable (by clone/copy)

leave a comment »

Every now and then I completely forget that the Request.QueryString (and Request.Form) object is read-only. Today I had a bit of functionality where I needed to remove a key/value from the collection – but the Remove() method (of the NameValueCollection object) throws an exception.

Unfortunately, the Request.QueryString‘s CopyTo method assigns the values to an ARRAY, not a NameValueCollection – losing functionality and flexibility.

You need to copy the Request.QueryString object to a new NameValueCollection instance, here’s how:

NameValueCollection qs = new NameValueCollection(Request.QueryString);

Now you can add/remove the key/values to your hearts content!

Oh, yeah, remember to import the System.Collections.Specialized namespace too!

Written by Lee Kelleher

June 6, 2008 at 1:09 pm

Posted in blog

Tagged with , , , ,

Posting source code on WordPress.com

with one comment

I feel like a complete n00b … I’ve only just found out how to mark-up source-code snippets on WordPress.com

It’s in their FAQs: How do I post source code?

Essentially you use the short-code: [sourcecode language='css']...[/sourcecode]

Here’s an example:

// A "Hello World!" program in C#
class Hello
{
   static void Main()
   {
      System.Console.WriteLine("Hello World!");
   }
}

I knew about WP.org plugins that did this, but I’ve been scratching my head on how do this on WP.com for ages now!

Written by Lee Kelleher

April 23, 2008 at 9:55 am

Posted in blog

Tagged with , , , ,