diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs
index c4965d7fa2..049a5baa9a 100644
--- a/src/Umbraco.Core/Models/Property.cs
+++ b/src/Umbraco.Core/Models/Property.cs
@@ -32,8 +32,9 @@ namespace Umbraco.Core.Models
Value = value;
}
- public Property(PropertyType propertyType, object value, Guid version)
+ public Property(int id, Guid version, PropertyType propertyType, object value)
{
+ Id = id;
_propertyType = propertyType;
_version = version;
Value = value;
diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs
index 8f978673c9..15c4737715 100644
--- a/src/Umbraco.Core/Models/PropertyExtensions.cs
+++ b/src/Umbraco.Core/Models/PropertyExtensions.cs
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Models
/// Xml of the property and its value
public static XElement ToXml(this Property property)
{
- string nodeName = property.Alias.ToUmbracoAlias();
+ string nodeName = property.Alias.ToUmbracoAlias(StringAliasCaseType.CamelCase, true);
var xd = new XmlDocument();
XmlNode xmlNode = xd.CreateNode(XmlNodeType.Element, nodeName, "");
diff --git a/src/Umbraco.Core/Models/PropertyType.cs b/src/Umbraco.Core/Models/PropertyType.cs
index 7a1213820e..95fc2648ce 100644
--- a/src/Umbraco.Core/Models/PropertyType.cs
+++ b/src/Umbraco.Core/Models/PropertyType.cs
@@ -209,10 +209,12 @@ namespace Umbraco.Core.Models
///
/// Can be used for the "old" values where no serialization type exists
///
+ ///
+ ///
///
- internal Property CreatePropertyFromRawValue(object value)
+ internal Property CreatePropertyFromRawValue(object value, Guid version, int id)
{
- return new Property(this, value);
+ return new Property(id, version, this, value);
}
///
diff --git a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs
index f846db0f86..ccd2071b76 100644
--- a/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs
+++ b/src/Umbraco.Core/Persistence/Factories/PropertyFactory.cs
@@ -35,7 +35,9 @@ namespace Umbraco.Core.Persistence.Factories
foreach (var dto in dtos)
{
var propertyType = _contentType.CompositionPropertyTypes.FirstOrDefault(x => x.Id == dto.PropertyTypeId);
- properties.Add(propertyType.CreatePropertyFromRawValue(dto.GetValue));
+ var property = propertyType.CreatePropertyFromRawValue(dto.GetValue, dto.VersionId.Value, dto.Id);
+ property.ResetDirtyProperties();
+ properties.Add(property);
}
return properties;
}
@@ -85,7 +87,9 @@ namespace Umbraco.Core.Persistence.Factories
foreach (var dto in dtos)
{
var propertyType = _mediaType.PropertyTypes.FirstOrDefault(x => x.Id == dto.PropertyTypeId);
- properties.Add(propertyType.CreatePropertyFromRawValue(dto.GetValue));
+ var property = propertyType.CreatePropertyFromRawValue(dto.GetValue, dto.VersionId.Value, dto.Id);
+ property.ResetDirtyProperties();
+ properties.Add(property);
}
return properties;
}
diff --git a/src/Umbraco.Core/Services/IContentTypeService.cs b/src/Umbraco.Core/Services/IContentTypeService.cs
index f1881fea0c..d4d11493b8 100644
--- a/src/Umbraco.Core/Services/IContentTypeService.cs
+++ b/src/Umbraco.Core/Services/IContentTypeService.cs
@@ -115,5 +115,17 @@ namespace Umbraco.Core.Services
/// Collection of to delete
/// Deleting a will delete all the objects based on this
void Delete(IEnumerable mediaTypes);
+
+ ///
+ /// Generates the complete (simplified) XML DTD.
+ ///
+ /// The DTD as a string
+ string GetDtd();
+
+ ///
+ /// Generates the complete XML DTD without the root.
+ ///
+ /// The DTD as a string
+ string GetContentTypesDtd();
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/XmlExtensions.cs b/src/Umbraco.Core/XmlExtensions.cs
index 7757d25fda..2ef5ede802 100644
--- a/src/Umbraco.Core/XmlExtensions.cs
+++ b/src/Umbraco.Core/XmlExtensions.cs
@@ -39,7 +39,16 @@ namespace Umbraco.Core
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
- return xmlDoc;
+ return xmlDoc.FirstChild;
+ }
+ }
+
+ public static XmlNode GetXmlNode(this XElement element, XmlDocument xmlDoc)
+ {
+ using (XmlReader xmlReader = element.CreateReader())
+ {
+ xmlDoc.Load(xmlReader);
+ return xmlDoc.DocumentElement;
}
}
}
diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config
index 729b7c1809..c899acb040 100644
--- a/src/Umbraco.Tests/App.config
+++ b/src/Umbraco.Tests/App.config
@@ -104,4 +104,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs
index 88ab06d263..5035920fc8 100644
--- a/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs
+++ b/src/Umbraco.Tests/Publishing/PublishingStrategyTests.cs
@@ -1,8 +1,10 @@
using System;
using System.Web;
+using System.Xml;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
+using Umbraco.Core.ObjectResolution;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Web.Strategies;
@@ -38,10 +40,19 @@ namespace Umbraco.Tests.Publishing
[TearDown]
public override void TearDown()
{
- base.TearDown();
+ DatabaseContext.Database.Dispose();
+
+ //TestHelper.ClearDatabase();
+
+ //reset the app context
+ ApplicationContext.Current = null;
+ Resolution.IsFrozen = false;
+
+ string path = TestHelper.CurrentAssemblyDirectory;
+ AppDomain.CurrentDomain.SetData("DataDirectory", null);
}
- [Test, Ignore]
+ [Test]
public void Can_Publish_And_Update_Xml_Cache()
{
// Arrange
@@ -56,6 +67,11 @@ namespace Umbraco.Tests.Publishing
// Assert
Assert.That(published, Is.True);
Assert.That(content.Published, Is.True);
+ Assert.IsTrue(httpContext.Items.Contains("UmbracoXmlContextContent"));
+
+ var document = httpContext.Items["UmbracoXmlContextContent"] as XmlDocument;
+ Console.Write(document.OuterXml);
+ document.Save("umbraco.config");
}
public void CreateTestData()
diff --git a/src/Umbraco.Web/Services/ContentTypeService.cs b/src/Umbraco.Web/Services/ContentTypeService.cs
index 25e7e250c1..5519169237 100644
--- a/src/Umbraco.Web/Services/ContentTypeService.cs
+++ b/src/Umbraco.Web/Services/ContentTypeService.cs
@@ -1,11 +1,15 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
+using System.Text;
+using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
+using umbraco;
namespace Umbraco.Web.Services
{
@@ -260,5 +264,61 @@ namespace Umbraco.Web.Services
}
_unitOfWork.Commit();
}
+
+ ///
+ /// Generates the complete (simplified) XML DTD.
+ ///
+ /// The DTD as a string
+ public string GetDtd()
+ {
+ var dtd = new StringBuilder();
+ dtd.AppendLine("");
+
+ return dtd.ToString();
+ }
+
+ ///
+ /// Generates the complete XML DTD without the root.
+ ///
+ /// The DTD as a string
+ public string GetContentTypesDtd()
+ {
+ var dtd = new StringBuilder();
+ if (UmbracoSettings.UseLegacyXmlSchema)
+ {
+ dtd.AppendLine(" ");
+ }
+ else
+ {
+ try
+ {
+ var strictSchemaBuilder = new StringBuilder();
+
+ var contentTypes = GetAllContentTypes();
+ foreach (ContentType contentType in contentTypes)
+ {
+ string safeAlias = contentType.Alias.ToUmbracoAlias(StringAliasCaseType.CamelCase, true);
+ if (safeAlias != null)
+ {
+ strictSchemaBuilder.AppendLine(String.Format("", safeAlias));
+ strictSchemaBuilder.AppendLine(String.Format("", safeAlias));
+ }
+ }
+
+ // Only commit the strong schema to the container if we didn't generate an error building it
+ dtd.Append(strictSchemaBuilder);
+ }
+ catch (Exception exception)
+ {
+ // Note, Log.Add quietly swallows the exception if it can't write to the database
+ //Log.Add(LogTypes.System, -1, string.Format("{0} while trying to build DTD for Xml schema; is Umbraco installed correctly and the connection string configured?", exception.Message));
+ }
+
+ }
+ return dtd.ToString();
+ }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Strategies/UpdateContentCache.cs b/src/Umbraco.Web/Strategies/UpdateContentCache.cs
index ae70dc1ae9..b6642af010 100644
--- a/src/Umbraco.Web/Strategies/UpdateContentCache.cs
+++ b/src/Umbraco.Web/Strategies/UpdateContentCache.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Text;
using System.Web;
using System.Web.Caching;
using System.Xml;
@@ -9,22 +8,25 @@ using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Web.Publishing;
+using Umbraco.Web.Services;
using umbraco.interfaces;
using umbraco.presentation.nodeFactory;
using Node = umbraco.NodeFactory.Node;
namespace Umbraco.Web.Strategies
{
- public class UpdateContentCache : IApplicationStartupHandler
+ internal class UpdateContentCache : IApplicationStartupHandler
{
// Sync access to internal cache
private static readonly object XmlContentInternalSyncLock = new object();
private const string XmlContextContentItemKey = "UmbracoXmlContextContent";
private readonly HttpContextBase _httpContext;
+ private readonly ServiceContext _serviceContext;
public UpdateContentCache()
{
_httpContext = new HttpContextWrapper(HttpContext.Current);
+ _serviceContext = new ServiceContext(_httpContext);
PublishingStrategy.Published += PublishingStrategy_Published;
}
@@ -32,6 +34,7 @@ namespace Umbraco.Web.Strategies
public UpdateContentCache(HttpContextBase httpContext)
{
_httpContext = httpContext;
+ _serviceContext = new ServiceContext(_httpContext);
PublishingStrategy.Published += PublishingStrategy_Published;
}
@@ -57,7 +60,7 @@ namespace Umbraco.Web.Strategies
ClearContextCache();
- XmlContent = UpdateXmlAndSitemap(content, wip, true);
+ XmlContent = UpdateXmlAndSitemap(content, wip, false);//Update sitemap is usually set to true
}
// clear cached field values
@@ -88,7 +91,9 @@ namespace Umbraco.Web.Strategies
if (content.Published)
{
int parentId = content.Level == 1 ? -1 : content.ParentId;
- xmlContentCopy = AppendContentXml(content.Id, content.Level, parentId, content.ToXml(false).GetXmlNode(), xmlContentCopy);
+ var contentXmlNode = content.ToXml(false).GetXmlNode();
+ var xmlNode = xmlContentCopy.ImportNode(contentXmlNode, true);
+ xmlContentCopy = AppendContentXml(content.Id, content.Level, parentId, xmlNode, xmlContentCopy);
// update sitemapprovider
if (updateSitemapProvider && SiteMap.Provider is UmbracoSiteMapProvider)
@@ -96,7 +101,7 @@ namespace Umbraco.Web.Strategies
try
{
var prov = (UmbracoSiteMapProvider)SiteMap.Provider;
- global::umbraco.NodeFactory.Node n = new Node(content.Id, true);
+ var n = new Node(content.Id, true);
if (!String.IsNullOrEmpty(n.Url) && n.Url != "/#")
{
prov.UpdateNode(n);
@@ -127,7 +132,8 @@ namespace Umbraco.Web.Strategies
if (x == null && UmbracoSettings.UseLegacyXmlSchema == false)
{
//TODO Look into the validate schema method - seems a bit odd
- //xmlContentCopy = ValidateSchema(docNode.Name, xmlContentCopy);
+ //Move to Contract ?
+ xmlContentCopy = ValidateSchema(docNode.Name, xmlContentCopy);
if (xmlContentCopy != xmlContentCopy2)
docNode = xmlContentCopy.ImportNode(docNode, true);
}
@@ -148,6 +154,7 @@ namespace Umbraco.Web.Strategies
}
else
{
+ //TODO
//TransferValuesFromDocumentXmlToPublishedXml(docNode, x);
}
@@ -218,12 +225,7 @@ namespace Umbraco.Web.Strategies
if (content == null)
{
//content = global::umbraco.content.Instance.XmlContent;
-
- //TODO Move this to an extension method for the ContentType
- var dtd = new StringBuilder();
- dtd.AppendLine(" ");
- dtd.AppendLine("]>");
+ var dtd = _serviceContext.ContentTypeService.GetDtd();
content = new XmlDocument();
content.LoadXml(