public void Render(object source, HtmlTextWriter htmlWriter, TemplateDefinition liveDefinition)
		{
			var resolver = new PathResolver(liveDefinition.Folder);
			var hostPage = DNNContext.Current.Page;

			var args = new XsltArgumentList();
			args.AddExtensionObject("urn:ddrmenu", new XsltFunctions());
			args.AddExtensionObject("urn:dnngarden", new XsltFunctions());
			args.AddParam("ControlID", "", DNNContext.Current.HostControl.ClientID);
			args.AddParam("Options", "", ConvertToJson(liveDefinition.ClientOptions));
			args.AddParam("DNNPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Dnn)));
			args.AddParam("ManifestPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Manifest)));
			args.AddParam("PortalPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Portal)));
			args.AddParam("SkinPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Skin)));
			liveDefinition.TemplateArguments.ForEach(a => args.AddParam(a.Name, "", a.Value));

			HttpContext.Current.Items["Resolver"] = resolver;

			using (var xmlStream = new MemoryStream())
			{
				Utilities.SerialiserFor(source.GetType()).Serialize(xmlStream, source);
				xmlStream.Seek(0, SeekOrigin.Begin);
				xsl.Transform(XmlReader.Create(xmlStream), args, htmlWriter);
			}
		}
		internal static TemplateDefinition FromName(string templateName, string manifestName)
		{
			var manifestUrl = new PathResolver(null).Resolve(
				templateName + "/" + manifestName,
				PathResolver.RelativeTo.Container,
				PathResolver.RelativeTo.Skin,
				PathResolver.RelativeTo.Portal,
				PathResolver.RelativeTo.Module,
				PathResolver.RelativeTo.Dnn);
			return FromManifest(manifestUrl);
		}
        public void Render(object source, HtmlTextWriter htmlWriter, TemplateDefinition liveDefinition)
        {
            if (!(string.IsNullOrEmpty(liveDefinition.TemplateVirtualPath)))
            {
                var resolver = new PathResolver(liveDefinition.Folder);
                dynamic model = new ExpandoObject();
                model.Source = source;
                model.ControlID = DNNContext.Current.HostControl.ClientID;
                model.Options = ConvertToJson(liveDefinition.ClientOptions);
                model.DNNPath = resolver.Resolve("/", PathResolver.RelativeTo.Dnn);
                model.ManifestPath = resolver.Resolve("/", PathResolver.RelativeTo.Manifest);
                model.PortalPath = resolver.Resolve("/", PathResolver.RelativeTo.Portal);
                model.SkinPath = resolver.Resolve("/", PathResolver.RelativeTo.Skin);
                var modelDictionary = model as IDictionary<string, object>;
                liveDefinition.TemplateArguments.ForEach(a => modelDictionary.Add(a.Name, a.Value));

                var razorEngine = new RazorEngine(liveDefinition.TemplateVirtualPath, null, null);
                var writer = new StringWriter();
                razorEngine.Render<dynamic>(writer, model);

                htmlWriter.Write(writer.ToString());
            }
        }
		public void Render(object source, HtmlTextWriter htmlWriter, TemplateDefinition liveDefinition)
		{
			var resolver = new PathResolver(liveDefinition.Folder);
			var args = new XsltArgumentList();
			args.AddExtensionObject("urn:ddrmenu", new XsltFunctions());
			args.AddExtensionObject("urn:dnngarden", new XsltFunctions());
			args.AddParam("controlid", "", DNNContext.Current.HostControl.ClientID);
			args.AddParam("options", "", ConvertToJson(liveDefinition.ClientOptions));
			args.AddParam("dnnpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Dnn));
			args.AddParam("manifestpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Manifest));
			args.AddParam("portalpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Portal));
			args.AddParam("skinpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Skin));
			liveDefinition.TemplateArguments.ForEach(a => args.AddParam(a.Name.ToLowerInvariant(), "", a.Value));

			var sb = new StringBuilder();

			using (var xmlStream = new MemoryStream())
			using (var outputWriter = new StringWriter(sb))
			{
				Utilities.SerialiserFor(source.GetType()).Serialize(xmlStream, source);
				xmlStream.Seek(0, SeekOrigin.Begin);
				xsl.Transform(XmlReader.Create(xmlStream), args, outputWriter);
			}

			htmlWriter.Write(HttpUtility.HtmlDecode(sb.ToString()));
		}
		internal static TemplateDefinition FromManifest(string manifestUrl)
		{
			var httpContext = HttpContext.Current;
			var cache = httpContext.Cache;
			var manifestPath = httpContext.Server.MapPath(manifestUrl);

			var baseDef = cache[manifestPath] as TemplateDefinition;
			if (baseDef == null)
			{
				baseDef = new TemplateDefinition {Folder = Path.GetDirectoryName(manifestUrl)};

				var xml = new XmlDocument();
				xml.Load(manifestPath);

				var resolver = new PathResolver(baseDef.Folder);

				// ReSharper disable PossibleNullReferenceException
				foreach (XmlNode node in xml.DocumentElement.ChildNodes)
					// ReSharper restore PossibleNullReferenceException
				{
					if (node.NodeType == XmlNodeType.Element)
					{
						var elt = (XmlElement)node;
						switch (elt.LocalName)
						{
							case "template":
								baseDef.TemplateVirtualPath = GetResolvedPath(elt, resolver);
								baseDef.TemplatePath = httpContext.Server.MapPath(baseDef.TemplateVirtualPath);
								break;
							case "templateHead":
								baseDef.TemplateHeadPath = httpContext.Server.MapPath(GetResolvedPath(elt, resolver));
								break;
							case "scripts":
								foreach (XmlElement scriptElt in elt.GetElementsByTagName("script"))
								{
									var jsObject = scriptElt.GetAttribute("jsObject");
									var scriptPath = String.IsNullOrEmpty(scriptElt.InnerText.Trim())
									                 	? ""
									                 	: Globals.ResolveUrl(GetResolvedPath(scriptElt, resolver));
									var key = String.IsNullOrEmpty(jsObject) ? scriptPath : jsObject;
									var script = CreateScript(jsObject, scriptPath);
									if (!String.IsNullOrEmpty(script))
									{
										baseDef.ScriptKeys.Add(key);
										baseDef.Scripts.Add(key, script);
									}
								}
								break;
							case "stylesheets":
								foreach (XmlElement cssElt in elt.GetElementsByTagName("stylesheet"))
								{
									var cssPath = Globals.ResolveUrl(GetResolvedPath(cssElt, resolver));
									baseDef.StyleSheets.Add(cssPath);
								}
								break;
							case "defaultClientOptions":
								foreach (XmlElement optionElt in elt.GetElementsByTagName("clientOption"))
								{
									var optionName = optionElt.GetAttribute("name");
									var optionType = optionElt.GetAttribute("type");
									var optionValue = optionElt.GetAttribute("value");
									if (String.IsNullOrEmpty(optionType))
									{
										optionType = "passthrough";
									}
									switch (optionType)
									{
										case "number":
											baseDef.DefaultClientOptions.Add(new ClientNumber(optionName, optionValue));
											break;
										case "boolean":
											baseDef.DefaultClientOptions.Add(new ClientBoolean(optionName, optionValue));
											break;
										case "string":
											baseDef.DefaultClientOptions.Add(new ClientString(optionName, optionValue));
											break;
										default:
											baseDef.DefaultClientOptions.Add(new ClientOption(optionName, optionValue));
											break;
									}
								}
								break;
							case "defaultTemplateArguments":
								foreach (XmlElement argElt in elt.GetElementsByTagName("templateArgument"))
								{
									var argName = argElt.GetAttribute("name");
									var argValue = argElt.GetAttribute("value");
									baseDef.DefaultTemplateArguments.Add(new TemplateArgument(argName, argValue));
								}
								break;
						}
					}
				}

				foreach (var processor in DNNAbstract.SupportedTemplateProcessors())
				{
					if (processor.LoadDefinition(baseDef))
					{
						baseDef.Processor = processor;
						break;
					}
				}

				if (baseDef.Processor == null)
				{
					throw new ApplicationException(String.Format("Can't find processor for manifest {0}", manifestPath));
				}

				cache.Insert(manifestPath, baseDef, new CacheDependency(new[] {manifestPath, baseDef.TemplatePath}));
			}

			var result = baseDef.Clone();
			result.Reset();
			return result;
		}
		private static string GetResolvedPath(XmlNode scriptElt, PathResolver pathResolver)
		{
			return pathResolver.Resolve(
				scriptElt.InnerText.Trim(),
				PathResolver.RelativeTo.Manifest,
				PathResolver.RelativeTo.Skin,
				PathResolver.RelativeTo.Module,
				PathResolver.RelativeTo.Portal,
				PathResolver.RelativeTo.Dnn);
		}