Just in Chronicles

Life as a Voyage

Archive for the ‘For .NET’ Category

Enhanced Preview for Umbraco

leave a comment »

Existing preview function in Umbraco only supports actual pages, not contents shared within a website. This approach is logically correct as shared contents are not independent pages. However, there must be demands to preview shared contents before publishing them.

This Umbraco extension enables for content editors to preview what they have written and how the contents would be looking like, before they publish the contents.

Basic idea is simple. Umbraco provides an alternative template function by using AltTemplate querystring.

This extension allows users to assign certain document types to templates. So, when users click the preview button, this extension starts looking up the configuration values to for document type  – template mappings.

<enhancedPreviewConfiguration>
    <items>
        <clear />
        <add alias="Product" template="StandardPage" redirectUrl="/products/product/{0}" />
        <add alias="Company" template="StandardPage" redirectUrl="/companies/company/{0}" />
    </items>
</enhancedPreviewConfiguration>

Like the example above, the extension registers a config file, EnhancedPreviewConfiguration.config under /config/ directory. Based on this example, a document type Product will use the template StandardPage for its preview mode. After the preview, the preview page will be redirected to /products/product/[productId] page.

If you guys are interested in, please visit the following websites.

Advertisements

Written by Justin Yoo

31/07/2012 at 17:20

Posted in For .NET

Tagged with , ,

Removing the “x_” Prefixes Injected by AntiXSS Library, from the “id” and “class” Attributes

leave a comment »

Microsoft Web Protection Library provides strong security protection while building a web site. By using this library, the web site can avoid XSS attacks. One of the benefits using this library is that the web site can sanitise users’ input, that means the HTML input can be filtered by the library.

However, during the sanitisation process, a prefix, "x_", intentionally prepends both "id" and "class" attributes of each HTML element. The reason is that the sanitisation process cannot guarantee which "id" and "class" values are safe or not, so each "id" and "class" attribute have their prefix "x_" as a result. This is, of course, not desirable. So, developers have to get rid of those prefixes from the HTML output.

public static string RemoveSanitisedPrefixes(string html)
{
	Match match = Regex.Match(html, "(id|class)=\"?(x_).+\"?", RegexOptions.IgnoreCase);
	if (match.Success)
	{
		string key = match.Groups[2].Value;
		html = html.Replace(key, "");
	}
	return html;
}

Once your HTML contents are sanitised by Microsoft.Security.Application.GetSafeHtml() or Microsoft.Security.Application.GetSafeHtmlFragment(), pass the sanitised HTML value to the method above, and you’ll get the "x_" removed HTML contents.

Written by Justin Yoo

16/04/2012 at 13:25

Quiz: 3-6-9 Game with Your Programming Language

leave a comment »

There is a very popular game in Korea, called “3-6-9”. Its rule is very simple:

  • A player starts counting from 1.
  • Next player count the number added 1. Repeat this rule until one player fails counting.
  • However, when a player meets a number containing digits such as 3, 6, or 9, the person has to do a clap for the number of times.
  • This is the example of playing:
    • 1, 2, “clap” (3), 4, 5, “clap” (6), 7, 8, “clap” (9), 10, 11, 12, “clap” (13), 14, 15, “clap” (16), 17, 18, “clap” (19), 20, 21, 22, “clap” (23), 24, 25, “clap” (26), 27, 28, “clap”  (29), “clap” (30), “clap” (31), “clap” (32), “clap clap” (33), “clap” (34), “clap” (35), “clap clap” (36), “clap” (37), “clap” (38), “clap clap” (39), 40, 41, 42, “clap” (43), …

The question is…

Use your preferred programming language, create a function or method to perform this game up to 100.

And my solution using C# is… (substituted “clap” with “X”)

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Aliencube.Quizes
{
	public partial class ThreeSixNine
	{
		public static string Execute(int maxNumber = 100)
		{
			List<string> results = new List<string>();
			for (int i = 1; i <= maxNumber; i++)
			{
				int xs = Regex.Matches(Convert.ToString(i), "[369]").Count;
				results.Add(xs == 0 ? Convert.ToString(i) : new String('X', xs));
			}
			return String.Join(" ", results);
		}
	}
}

How’s yours guys?

Written by Justin Yoo

15/04/2012 at 18:36

Posted in For .NET

Triming Property Type Value – Description or Validation – While Saving Document Type in Umbraco

leave a comment »

When developers create a document type in Umbraco, they might notice that an extra line – either Line Feed (\n) or Carriage Return (\r), or both – is added into those two fields – Validation and Description – of each property. This extra white space will result in validation errors and prevent the content from saving, in the Content section.

In order to avoid this, the value must be trimmed while retrieving and saving by modifying the source code, UmbracoProject\umbraco\cms\businesslogic\propertytype\propertytype.cs. Find the following code lines from the file and put .Trim() as highlighted.

public string ValidationRegExp
{
	get { return _validationRegExp.Trim(); }
	set
	{
		_validationRegExp = value.Trim();
		InvalidateCache();
		SqlHelper.ExecuteNonQuery(
			"Update cmsPropertyType set validationRegExp = @validationRegExp where id = @id",
			SqlHelper.CreateParameter("@validationRegExp", value.Trim()), SqlHelper.CreateParameter("@id", Id));
	}
}
public string Description
{
	get
	{
		if (_description != null)
		{
			if (!_description.StartsWith("#"))
				return _description.Trim();
			else
			{
				Language lang = Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name);
				if (lang != null)
				{
					if (Dictionary.DictionaryItem.hasKey(_description.Substring(1, _description.Length - 1)))
					{
						var di =
							new Dictionary.DictionaryItem(_description.Substring(1, _description.Length - 1));
						return di.Value(lang.id).Trim();
					}
				}
			}

			return "[" + _description.Trim() + "]";
		}

		return _description.Trim();
	}
	set
	{
		_description = value.Trim();
		InvalidateCache();
		SqlHelper.ExecuteNonQuery(
			"Update cmsPropertyType set description = @description where id = @id",
			SqlHelper.CreateParameter("@description", value.Trim()),
			SqlHelper.CreateParameter("@id", Id));
	}
}
public string GetRawDescription()
{
	return _description.Trim();
}

By adding the .Trim() method, even though it can’t prevent displaying an extra line, but it won’t save the extra line into the database.

Written by Justin Yoo

27/03/2012 at 18:12

uComponents: Multi-Node Tree Picker Data Saving Format Error in Umbraco

leave a comment »

uComponents is a killer extension for Umbraco as it compliments a lot of features that Umbraco lacks or doesn’t have. Nowadays uComponents is a sort of de-facto standard extension because many other extensions are assuming that uComponents is installed.

Once uComponents is installed, several data types used in Umbraco are also installed. Multi-Node Tree Picker (MNTP) which is one of the installed data types is, I believe, the most useful and versatile data type. However, it stores its value as NTEXT type when its value type is set to CSV, which is not quite right.

When you modify contents at the Umbraco back-office, the following error message can be seen.

Your data has been saved, but before you can publish this page there are some errors you need to fix first:

  • [PROPERTY] at [TAB] is not in a correct format

This results from the fact that the value type is set to NTEXT, instead of NVARCHAR. So, once a data type using MNTP is created, the value type should be updated to NVARCHAR directly in SQL.

SELECT
	node.id,
	node.[text],
	dt.*
FROM
	cmsDataType AS dt
	JOIN umbracoNode AS node
		ON dt.nodeId = node.id
WHERE
	dt.controlId = 'c2d6894b-e788-4425-bcf2-308568e3d38b'

Note that the controlId has the value “c2d6894b-e788-4425-bcf2-308568e3d38b” that represents MNTP. Once the query is run, all MNTP data types are listed. They all have NText at their dbType. So they need to be updated to NVarchar by running the following SQL script.

UPDATE
	cmsDataType
   SET
	dbType = 'Nvarchar'
 WHERE
	controlId = 'c2d6894b-e788-4425-bcf2-308568e3d38b'

Now, the MNTP control will have NVarchar data value and will not display the error message above.

Written by Justin Yoo

26/03/2012 at 13:56

How to Get List of Countries Defined in ISO 3166-1 Programatically by C#

with one comment

ISO 3166-1 defines the list of countries currently existing in the world while ISO 639-1 defines the list of languages currently and officially used all over the world. What if we need to display the list of countries do developers usually try? We can think of creating a meta table in a database or an XML file for reference.

Fortunately, .NET framework provides System.Globalization namespace to handle culture specific data such as date and time format, currency format and so forth. This is particularly useful for applications considering I18N or L10N.

There are two classes called CultureInfo and RegionInfo in the System.Globalization namespace. CultureInfo detects current system environment and returns the current culture including language, country, currency, time and date. It also returns a specific culture information by manually initialising the culture code. A CultureInfo object contains both language code defined by ISO 639-1 and country code defined by ISO 3166-1. By using this information, we can programmatically returns the list of countries.

/// <summary>
/// Gets the list of countries based on ISO 3166-1
/// </summary>
/// <returns>Returns the list of countries based on ISO 3166-1</returns>
public static List<RegionInfo> GetCountriesByIso3166()
{
	List<RegionInfo> countries = new List<RegionInfo>();
	foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
	{
		RegionInfo country = new RegionInfo(culture.LCID);
		if (countries.Where(p => p.Name == country.Name).Count() == 0)
			countries.Add(country);
	}
	return countries.OrderBy(p => p.EnglishName).ToList();
}

Let’s see the highlighted line 8 above. Firstly, we need list up all cultures and create RegionInfo objects based on the culture. As a CultureInfo object has both language code and country code and some CultureInfo objects have common country code, eg. en-CA (English in Canada), fr-CA (French in Canada), we need to take only one RegionInfo object (line 10-12).

/// <summary>
/// Gets the list of countries by selected country codes.
/// </summary>
/// <param name="code">List of culture codes.</param>
/// <returns>Returns the list of countries by selected country codes.</returns>
public static List<RegionInfo> GetCountriesByCode(List<string> codes)
{
	List<RegionInfo> countries = new List<RegionInfo>();
	if (codes != null && codes.Count > 0)
	{
		foreach (string code in codes)
		{
			try
			{
				countries.Add(new RegionInfo(code));
			}
			catch
			{
				//	Ignores the invalid culture code.
			}
		}
	}
	return countries.OrderBy(p => p.EnglishName).ToList();
}

We can also get the list of countries from the country codes provided like above. Make sure that we need to use the try...catch... block (line 19) to ignore the invalid country code used. This code can be more improved by using various types of codes.

Written by Justin Yoo

15/03/2012 at 08:00

How to Add External Error Log to Umbraco with Razor Macro Scripts

leave a comment »

Umbraco Razor macro script is very powerful and handy solution for developers to implement websites quite easily, while XSLT scripts are very hard to read and understand. However, using Razor macro scripts in Umbraco calls error log functions internally, which saves the logs to the database, rather than specific files.

That sometimes gets developers bothered as they have to append “umbDebutShotTrace=true” query string to its URL to debug an error when it occurs. Besides using the “umbDebugShowTrace=true” option, developers want to save that error details to a specific location other than the database. In order to achieve this, Umbraco core needs to be modified and recompiled. The key method is “umbraco.MacroEngines.RazorMacroEngine.Execute()” which is coded in “/umbraco.MacroEngines.Juno/RazorCore/RazorMacroEngine.cs“. Let’s see the code.

public string Execute(MacroModel macro, INode currentPage)
{
	try
	{
		Success = true;
		return ExecuteRazor(macro, currentPage);
	}
	catch (Exception exception)
	{
		Success = false;
		ResultException = exception;
		HttpContext.Current.Trace.Warn("umbracoMacro", string.Format("Error Loading Razor Script (file: {0}) {1} {2}", macro.Name, exception.Message, exception.StackTrace));
		var loading = string.Format("<div style=\"border: 1px solid #990000\">Error loading Razor Script {0}</br/>", macro.ScriptName);
		if (GlobalSettings.DebugMode)
			loading = loading + exception.Message;
		loading = loading + "</div>";

		// Adds the exception to the current HttpContext.Items.
		// Option #1: Using Dictionary<T>
		List<Dictionary<string, string>> logs = (List<Dictionary<string, string>>)HttpContext.Current.Items["umbracoErrorLogItems"];
		if (logs == null)
			logs = new List<Dictionary<string, string>>();
		logs.Add(new Dictionary<string, string>() { { "message", exception.Message }, { "source", exception.Source }, { "stackTrace", exception.StackTrace } });

		// Option #2: Using general Object
		List<object> logs = (List<object>)HttpContext.Current.Items["umbracoErrorLogItems"];
		if (logs == null)
			logs = new List<object>();
		logs.Add(new { Message = exception.Message, Source = exception.Source, StackTrace = exception.StackTrace });

		HttpContext.Current.Items["umbracoErrorLogItems"] = logs;
		return loading;
	}
}

The lines highlighted between 18 and 29 are newly added for the external log saving mechanism. When an exception occurs, HttpContext.Current.Items[“umbracoErrorLogItems”] stores the error details. Option #1 uses Dictionary<T> while Option #2 uses general object.

Then, open the /default.aspx page of the website’s root directory and put the following code bits.

<script runat="server">
	protected void Page_Load(object sender, EventArgs e)
	{
		var logs = Context.Items["umbracoErrorLogItems"];
		if (logs != null)
		{
			foreach (var log in logs)
			YourLogHelper.SaveLog(log);
			Context.Items["umbracoErrorLogItems"] = null;
		}
	}
</script>

Once the page is loaded, if there is any error log details found from HttpContext.Current.Items[“umbracoErrorLogItems”], the highlighted log saving method will be executed. Once all the error log details are saved, the Context.Items[“umbracoErrorLogItems”] has to be cleared for further use.

That’s what I’ve found so far. I know modifying the core source code is not the ideal solution, but it this case might be excused.

Written by Justin Yoo

06/03/2012 at 18:01

Posted in For .NET

Tagged with , ,