Pages

Showing posts with label extension methods. Show all posts
Showing posts with label extension methods. Show all posts

Thursday, January 14, 2010

Randomize a List<T>

Here's another instalment in a sporadic series of useful C# extension methods. This time we return a List in a random order:

public static class ICollectionExtensions
{
/// <summary>
/// Randomizes the specified source.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <returns></returns>
public static ICollection<T> Randomize(this ICollection<T> source)
{
Random rng = new Random();

T[] a = new T[source.Count];
source.CopyTo(a, 0);

byte[] b = new byte[a.Length];
rng.NextBytes(b);

Array.Sort(b, a);

return new List<T>(a);
}
}

Thursday, October 22, 2009

More EpiServer extension methods

Here's another extension method for returning a normal EpiServer Url to a page from a LinkItem (from a PropertyLinkCollection).

public static class LinkItemExtensions
{
public static string ToExternal(this LinkItem item)
{
string externalUrl = item.Href;

PermanentLinkMapStore.TryToMapped(item.Href, out externalUrl);

return externalUrl;
}
}


I'm using the PermanentLinkMapStore following a read of this post.

I've been using it when binding a LinkItemCollection to a ListView like this:
PropertyLinkCollection linksProperty = CurrentPage.ToProperty("Links");

var links = from l in linksProperty.Links
select new
{
Href = l.ToExternal(),
Title = l.Title,
Text = l.Text,
Extension = Path.GetExtension(l.Href)
};

lvLinks.DataSource = links;
lvLinks.DataBind();

Wednesday, October 14, 2009

EpiServer Extension methods

Following on from my previous post I realised that the majority of the Extension methods that I use in everyday coding are EpiServer related.

Here are some really useful ones:


/// <summary>
/// Gets the children.
/// </summary>
/// <param name="page">The page.</param>
/// <returns></returns>
public static PageDataCollection GetChildren(this PageData page)
{
PageDataCollection children = new PageDataCollection();

if (page.PageLink != null && page.PageLink.ID > 0)
{
children = DataFactory.Instance.GetChildren(page.PageLink);

FilterPublished publishedDateFilter = new FilterPublished(PagePublishedStatus.Published);
FilterSort indexSorter = new EPiServer.Filters.FilterSort(FilterSortOrder.Index);

publishedDateFilter.Filter(children);
indexSorter.Sort(children);
}

return children;
}

/// <summary>
/// Gets the external URL.
/// </summary>
/// <param name="page">The page.</param>
/// <returns></returns>
public static string GetExternalUrl(this PageData page)
{
string result = String.Empty;

if (page != null)
{
UrlBuilder builder = new UrlBuilder(page.LinkURL);

EPiServer.Global.UrlRewriteProvider.ConvertToExternal(builder, page, Encoding.UTF8);

result = builder.ToString();
}

return result;
}


/// <summary>
/// Returns a concrete PropertyData (or child class)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="page">The page.</param>
/// <param name="propertyName">Name of the property.</param>
/// <returns></returns>
public static T ToProperty<T>(this PageData page, string propertyName) where T : PropertyData
{
return page.Property[propertyName] as T;
}

/// <summary>
/// Returns a PageData property or string.Empty if null
/// </summary>
/// <param name="page">The page.</param>
/// <param name="propertyName">Name of the property.</param>
/// <returns></returns>
public static string SafeProperty(this PageData page, string propertyName)
{
return (page.HasProperty(propertyName)) ? page[propertyName].ToString() : string.Empty;
}


/// <summary>
/// Gets the page for a Pagereference.
/// </summary>
/// <param name="pageRef">The Pagereference.</param>
/// <returns></returns>
public static PageData GetPage(this PageReference pageRef)
{
return DataFactory.Instance.GetPage(pageRef);
}

Some useful Extensions methods

Extension methods have been around a while now and I like them more every day. Oh I know they are just aliased static methods, but they are convenient for small common situations where it seems like the framework developers missed something out.

Here's a few of my that I find useful:

NameValueCollection Extensions:

/// <summary>
/// Returns the collectionas a standard URL type QueryString
/// </summary>
/// <param name="self">The self.</param>
/// <returns></returns>
public static string ToQueryString(this NameValueCollection self)
{
string qsString = string.Empty;
if (self.Count > 0)
{
StringBuilder qsBuilder = new StringBuilder("?");

for (int i = 0; i < self.Keys.Count; i++)
{
if (self.Keys[i] != null && self.Keys[i].Length > 0)
{
qsBuilder.AppendFormat("{0}={1}&", HttpContext.Current.Server.UrlEncode(self.Keys[i]), HttpContext.Current.Server.UrlEncode(self[i]));
}
}

qsString = qsBuilder.ToString();
}

return qsString;
}


/// <summary>
/// Creates a copy the specified NameValueCollection.
/// </summary>
/// <param name="self">The NameValueCollection.</param>
/// <returns></returns>
public static NameValueCollection Copy(this NameValueCollection self)
{
return new NameValueCollection(self);
}


String Extensions

/// <summary>
/// Capitalizes the specified word.
/// </summary>
/// <param name="word">The word.</param>
/// <returns></returns>
public static string Capitalize(this string word)
{
if (word.IsNullOrEmpty())
{
return word;
}

// The aggregate is because IEnumerable.ToString doesn't return the characters as a string, it returns the type's name as a string.
return word[0].ToString().ToUpper() + word.Skip(1).Aggregate("", (s, c) => s + c);
}


/// <summary>
/// Splits the specified string into a list of white-space separated word strings.
/// </summary>
/// <param name="s">The s.</param>
/// <returns></returns>
public static IEnumerable Wordify(this string s)
{
return s.Split(new char[]{' ', '\n', '\t', '\r', '.', ',', ';', ':', '-'}, StringSplitOptions.RemoveEmptyEntries);
}

Thursday, June 18, 2009

Simple UrlRewriter for EpiServer

On an EpiServer project that I just finished there was a requirement that all URLs generated by the CMS should be lowercase. I couldn't really see the issue. I know that web servers are allowed to be case sensitive with URLs, but didn't really see the big deal.

However, looking at EpiServer, I thught that I might re-write a PageData extension method which I wrote previously which generates the external URL of a page:

public static string GetExternalUrl(this PageData page)
{
string result = String.Empty;

if (page != null)
{
UrlBuilder builder = new UrlBuilder(page.LinkURL);
EPiServer.Global.UrlRewriteProvider.ConvertToExternal
(builder, page, Encoding.UTF8);

result = builder.ToString();
}

return result;
}

This might have worked, but was still a bit of a kludge, so I turned to the undocumented waters of the EPiServer.Web.FriendlyUrlRewriteProvider

The FriendlyUrlRewriteProvider has a virtual method called:

ConvertToExternalInternal(EPiServer.UrlBuilder url, object internalObject, Encoding toEncoding)

Which is called by the EPiServer.Global.UrlRewriteProvider.ConvertToExternal(...) method I use in the Extension method above. Overriding that mehtod and converting the UrlBuilder's path property to lowercase seemed to do the trick.

Here's the final class:

public class LowerCaseUrlRewriteProvider : EPiServer.Web.FriendlyUrlRewriteProvider
{
public LowerCaseUrlRewriteProvider()
: base()
{

}

protected override bool ConvertToExternalInternal
(EPiServer.UrlBuilder url, object internalObject, Encoding toEncoding)
{
base.ConvertToExternalInternal(url, internalObject, toEncoding);

url.Path = url.Path.ToLower();

return true;
}
}



Update: Setting it up in the Web.Config

You now need to add this to the urlRewrite EpiServer config element in the Web.Config:

<urlRewrite defaultProvider="LowerCaseUrlRewriteProvider">
<providers>
<add name="LowerCaseUrlRewriteProvider" type="Shared.EpiServer.Web.LowerCaseUrlRewriteProvider,Shared.EpiServer" />
<add name="EPiServerFriendlyUrlRewriteProvider" type="EPiServer.Web.FriendlyUrlRewriteProvider,EPiServer" />
<add description="EPiServer identity URL rewriter" name="EPiServerIdentityUrlRewriteProvider"
type="EPiServer.Web.IdentityUrlRewriteProvider,EPiServer" />
<add description="EPiServer bypass URL rewriter" name="EPiServerNullUrlRewriteProvider"
type="EPiServer.Web.NullUrlRewriteProvider,EPiServer" />
</providers>
</urlRewrite>