diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs
index 438897cec8..b1603ed361 100644
--- a/src/Umbraco.Core/Services/ContentService.cs
+++ b/src/Umbraco.Core/Services/ContentService.cs
@@ -60,27 +60,8 @@ namespace Umbraco.Core.Services
///
public IContent CreateContent(string name, int parentId, string contentTypeAlias, int userId = 0)
{
- IContentType contentType = null;
- IContent content = null;
-
- var uow = _uowProvider.GetUnitOfWork();
- using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
- {
- var query = Query.Builder.Where(x => x.Alias == contentTypeAlias);
- var contentTypes = repository.GetByQuery(query);
-
- if (!contentTypes.Any())
- throw new Exception(string.Format("No ContentType matching the passed in Alias: '{0}' was found",
- contentTypeAlias));
-
- contentType = contentTypes.First();
-
- if (contentType == null)
- throw new Exception(string.Format("ContentType matching the passed in Alias: '{0}' was null",
- contentTypeAlias));
- }
-
- content = new Content(name, parentId, contentType);
+ IContentType contentType = FindContentTypeByAlias(contentTypeAlias);
+ IContent content = new Content(name, parentId, contentType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parentId), this))
return content;
@@ -106,27 +87,8 @@ namespace Umbraco.Core.Services
///
public IContent CreateContent(string name, IContent parent, string contentTypeAlias, int userId = 0)
{
- IContentType contentType = null;
- IContent content = null;
-
- var uow = _uowProvider.GetUnitOfWork();
- using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
- {
- var query = Query.Builder.Where(x => x.Alias == contentTypeAlias);
- var contentTypes = repository.GetByQuery(query);
-
- if (!contentTypes.Any())
- throw new Exception(string.Format("No ContentType matching the passed in Alias: '{0}' was found",
- contentTypeAlias));
-
- contentType = contentTypes.First();
-
- if (contentType == null)
- throw new Exception(string.Format("ContentType matching the passed in Alias: '{0}' was null",
- contentTypeAlias));
- }
-
- content = new Content(name, parent, contentType);
+ IContentType contentType = FindContentTypeByAlias(contentTypeAlias);
+ IContent content = new Content(name, parent, contentType);
if (Creating.IsRaisedEventCancelled(new NewEventArgs(content, contentTypeAlias, parent), this))
return content;
@@ -1002,6 +964,166 @@ namespace Umbraco.Core.Services
return content;
}
+ ///
+ /// Imports and saves package xml as
+ ///
+ /// Xml to import
+ /// An enumrable list of generated content
+ public IEnumerable Import(XElement element)
+ {
+ var name = element.Name.LocalName;
+ if (name.Equals("DocumentSet"))
+ {
+ //This is a regular deep-structured import
+ var roots = from doc in element.Elements()
+ where (string) doc.Attribute("isDoc") == ""
+ select doc;
+
+ var contents = ParseRootXml(roots);
+ Save(contents);
+
+ return contents;
+ }
+
+ var attribute = element.Attribute("isDoc");
+ if (attribute != null)
+ {
+ //This is a single doc import
+ var elements = new List { element };
+ var contents = ParseRootXml(elements);
+ Save(contents);
+
+ return contents;
+ }
+
+ throw new ArgumentException(
+ "The passed in XElement is not valid! It does not contain a root element called "+
+ "'DocumentSet' (for structured imports) nor is the first element a Document (for single document import).");
+ }
+
+ private IEnumerable ParseRootXml(IEnumerable roots)
+ {
+ var contentTypes = new Dictionary();
+ var contents = new List();
+ foreach (var root in roots)
+ {
+ bool isLegacySchema = root.Name.LocalName.ToLowerInvariant().Equals("node");
+ string contentTypeAlias = isLegacySchema
+ ? root.Attribute("nodeTypeAlias").Value
+ : root.Name.LocalName;
+
+ if (contentTypes.ContainsKey(contentTypeAlias) == false)
+ {
+ var contentType = FindContentTypeByAlias(contentTypeAlias);
+ contentTypes.Add(contentTypeAlias, contentType);
+ }
+
+ var content = CreateContentFromXml(root, contentTypes[contentTypeAlias], null, -1, isLegacySchema);
+ contents.Add(content);
+
+ var children = from child in root.Elements()
+ where (string)child.Attribute("isDoc") == ""
+ select child;
+ if(children.Any())
+ contents.AddRange(CreateContentFromXml(children, content, contentTypes, isLegacySchema));
+ }
+ return contents;
+ }
+
+ private IEnumerable CreateContentFromXml(IEnumerable children, IContent parent, Dictionary contentTypes, bool isLegacySchema)
+ {
+ var list = new List();
+ foreach (var child in children)
+ {
+ string contentTypeAlias = isLegacySchema
+ ? child.Attribute("nodeTypeAlias").Value
+ : child.Name.LocalName;
+
+ if (contentTypes.ContainsKey(contentTypeAlias) == false)
+ {
+ var contentType = FindContentTypeByAlias(contentTypeAlias);
+ contentTypes.Add(contentTypeAlias, contentType);
+ }
+
+ //Create and add the child to the list
+ var content = CreateContentFromXml(child, contentTypes[contentTypeAlias], parent, default(int), isLegacySchema);
+ list.Add(content);
+
+ //Recursive call
+ XElement child1 = child;
+ var grandChildren = from grand in child1.Elements()
+ where (string) grand.Attribute("isDoc") == ""
+ select grand;
+
+ if (grandChildren.Any())
+ list.AddRange(CreateContentFromXml(grandChildren, content, contentTypes, isLegacySchema));
+ }
+
+ return list;
+ }
+
+ private IContent CreateContentFromXml(XElement element, IContentType contentType, IContent parent, int parentId, bool isLegacySchema)
+ {
+ var id = element.Attribute("id").Value;
+ var level = element.Attribute("level").Value;
+ var sortOrder = element.Attribute("sortOrder").Value;
+ var nodeName = element.Attribute("nodeName").Value;
+ var path = element.Attribute("path").Value;
+ var template = element.Attribute("template").Value;
+
+ var properties = from property in element.Elements()
+ where property.Attribute("isDoc") == null
+ select property;
+
+ IContent content = parent == null
+ ? new Content(nodeName, parentId, contentType)
+ {
+ Level = int.Parse(level),
+ SortOrder = int.Parse(sortOrder)
+ }
+ : new Content(nodeName, parent, contentType)
+ {
+ Level = int.Parse(level),
+ SortOrder = int.Parse(sortOrder)
+ };
+
+ foreach (var property in properties)
+ {
+ string propertyTypeAlias = isLegacySchema ? property.Attribute("alias").Value : property.Name.LocalName;
+ if(content.HasProperty(propertyTypeAlias))
+ content.SetValue(propertyTypeAlias, property.Value);
+ }
+
+ return content;
+ }
+
+ private IContentType FindContentTypeByAlias(string contentTypeAlias)
+ {
+ using (var repository = _repositoryFactory.CreateContentTypeRepository(_uowProvider.GetUnitOfWork()))
+ {
+ var query = Query.Builder.Where(x => x.Alias == contentTypeAlias);
+ var types = repository.GetByQuery(query);
+
+ if (!types.Any())
+ throw new Exception(
+ string.Format("No ContentType matching the passed in Alias: '{0}' was found",
+ contentTypeAlias));
+
+ var contentType = types.First();
+
+ if (contentType == null)
+ throw new Exception(string.Format("ContentType matching the passed in Alias: '{0}' was null",
+ contentTypeAlias));
+
+ return contentType;
+ }
+ }
+
+ public XElement Export(IContent content, bool deep = false)
+ {
+ throw new NotImplementedException();
+ }
+
#region Internal Methods
///
/// Internal method to Re-Publishes all Content for legacy purposes.
diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs
index 75335cac0e..b7d51d46f8 100644
--- a/src/Umbraco.Core/Services/ContentTypeService.cs
+++ b/src/Umbraco.Core/Services/ContentTypeService.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Xml.Linq;
using Umbraco.Core.Auditing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Events;
@@ -460,6 +461,60 @@ namespace Umbraco.Core.Services
return dtd.ToString();
}
+ ///
+ /// Imports and saves package xml as
+ ///
+ /// Xml to import
+ /// An enumrable list of generated ContentTypes
+ public List Import(XElement element)
+ {
+ var name = element.Name.LocalName;
+ if (name.Equals("DocumentTypes") == false)
+ {
+ throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'DocumentTypes'.");
+ }
+
+ var list = new List();
+ var documentTypes = from doc in element.Elements("DocumentType") select doc;
+ foreach (var documentType in documentTypes)
+ {
+ //TODO Check if the ContentType already exists by looking up the alias
+ list.Add(CreateContentTypeFromXml(documentType));
+ }
+
+ Save(list);
+ return list;
+ }
+
+ private IContentType CreateContentTypeFromXml(XElement documentType)
+ {
+ var infoElement = documentType.Element("Info");
+ var name = infoElement.Element("Name").Value;
+ var alias = infoElement.Element("Alias").Value;
+ var masterElement = infoElement.Element("Master");//Name of the master corresponds to the parent
+ var icon = infoElement.Element("Icon").Value;
+ var thumbnail = infoElement.Element("Thumbnail").Value;
+ var description = infoElement.Element("Description").Value;
+ var allowAtRoot = infoElement.Element("AllowAtRoot").Value;
+ var defaultTemplate = infoElement.Element("DefaultTemplate").Value;
+ var allowedTemplatesElement = infoElement.Elements("AllowedTemplates");
+
+ var structureElement = documentType.Element("Structure");
+ var genericPropertiesElement = documentType.Element("GenericProperties");
+ var tabElement = documentType.Element("Tab");
+
+ var contentType = new ContentType(-1)
+ {
+ Alias = alias,
+ Name = name,
+ Icon = icon,
+ Thumbnail = thumbnail,
+ AllowedAsRoot = allowAtRoot.ToLowerInvariant().Equals("true"),
+ Description = description
+ };
+ return contentType;
+ }
+
#region Event Handlers
///
diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs
index 2d6871c1b3..9cc8edc5df 100644
--- a/src/Umbraco.Core/Services/IContentService.cs
+++ b/src/Umbraco.Core/Services/IContentService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Xml.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -287,5 +288,12 @@ namespace Umbraco.Core.Services
/// to check if anscestors are published
/// True if the Content can be published, otherwise False
bool IsPublishable(IContent content);
+
+ ///
+ /// Imports and saves package xml as
+ ///
+ /// Xml to import
+ /// An enumrable list of generated content
+ IEnumerable Import(XElement element);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/IContentTypeService.cs b/src/Umbraco.Core/Services/IContentTypeService.cs
index 15ee5d949c..4be9a9b492 100644
--- a/src/Umbraco.Core/Services/IContentTypeService.cs
+++ b/src/Umbraco.Core/Services/IContentTypeService.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Xml.Linq;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
@@ -149,5 +150,12 @@ namespace Umbraco.Core.Services
/// Id of the
/// True if the media type has any children otherwise False
bool MediaTypeHasChildren(int id);
+
+ ///
+ /// Imports and saves package xml as
+ ///
+ /// Xml to import
+ /// An enumrable list of generated ContentTypes
+ List Import(XElement element);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Services/Importing/ContentImportTests.cs b/src/Umbraco.Tests/Services/Importing/ContentImportTests.cs
new file mode 100644
index 0000000000..4ec48504a5
--- /dev/null
+++ b/src/Umbraco.Tests/Services/Importing/ContentImportTests.cs
@@ -0,0 +1,66 @@
+using System.Linq;
+using System.Xml.Linq;
+using NUnit.Framework;
+
+namespace Umbraco.Tests.Services.Importing
+{
+ [TestFixture, RequiresSTA]
+ public class ContentImportTests : BaseServiceTest
+ {
+ [SetUp]
+ public override void Initialize()
+ {
+ base.Initialize();
+ }
+
+ [TearDown]
+ public override void TearDown()
+ {
+ base.TearDown();
+ }
+
+ [Test]
+ public void ContentTypeService_Can_Import_Package_Xml()
+ {
+ // Arrange
+ string strXml = ImportResources.package;
+ var xml = XElement.Parse(strXml);
+ var element = xml.Descendants("DocumentTypes").First();
+ var contentTypeService = ServiceContext.ContentTypeService;
+
+ // Act
+ var contentTypes = contentTypeService.Import(element);
+ var numberOfDocTypes = (from doc in element.Elements("DocumentType") select doc).Count();
+
+ // Assert
+ Assert.That(contentTypes, Is.Not.Null);
+ Assert.That(contentTypes.Any(), Is.True);
+ Assert.That(contentTypes.Count(), Is.EqualTo(numberOfDocTypes));
+ }
+
+ [Test]
+ public void ContentService_Can_Import_Package_Xml()
+ {
+ // Arrange
+ string strXml = ImportResources.package;
+ var xml = XElement.Parse(strXml);
+ var docTypesElement = xml.Descendants("DocumentTypes").First();
+ var element = xml.Descendants("DocumentSet").First();
+ var contentService = ServiceContext.ContentService;
+ var contentTypeService = ServiceContext.ContentTypeService;
+
+ // Act
+ var contentTypes = contentTypeService.Import(docTypesElement);
+ var contents = contentService.Import(element);
+ var numberOfDocs = (from doc in element.Descendants()
+ where (string) doc.Attribute("isDoc") == ""
+ select doc).Count();
+
+ // Assert
+ Assert.That(contents, Is.Not.Null);
+ Assert.That(contentTypes.Any(), Is.True);
+ Assert.That(contents.Any(), Is.True);
+ Assert.That(contents.Count(), Is.EqualTo(numberOfDocs));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs b/src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs
new file mode 100644
index 0000000000..c46ae43bb5
--- /dev/null
+++ b/src/Umbraco.Tests/Services/Importing/ImportResources.Designer.cs
@@ -0,0 +1,90 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.18033
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Umbraco.Tests.Services.Importing {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class ImportResources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal ImportResources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Tests.Services.Importing.ImportResources", typeof(ImportResources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ ///<umbPackage>
+ /// <files>
+ /// <file>
+ /// <guid>Map.cshtml</guid>
+ /// <orgPath>/macroScripts</orgPath>
+ /// <orgName>Map.cshtml</orgName>
+ /// </file>
+ /// <file>
+ /// <guid>AccountController.cs</guid>
+ /// <orgPath>/App_Code</orgPath>
+ /// <orgName>AccountController.cs</orgName>
+ /// </file>
+ /// <file>
+ /// <guid>ContactController.cs</guid>
+ /// <orgPath>/App_Code</orgPath>
+ /// <orgName>ContactController.cs</orgName>
+ /// </file>
+ /// [rest of string was truncated]";.
+ ///
+ internal static string package {
+ get {
+ return ResourceManager.GetString("package", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/Umbraco.Tests/Services/Importing/ImportResources.resx b/src/Umbraco.Tests/Services/Importing/ImportResources.resx
new file mode 100644
index 0000000000..d277ad5aaf
--- /dev/null
+++ b/src/Umbraco.Tests/Services/Importing/ImportResources.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ package.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Tests/Services/Importing/package.xml b/src/Umbraco.Tests/Services/Importing/package.xml
new file mode 100644
index 0000000000..ddf3d5e66f
--- /dev/null
+++ b/src/Umbraco.Tests/Services/Importing/package.xml
@@ -0,0 +1,2278 @@
+
+
+
+
+ Map.cshtml
+ /macroScripts
+ Map.cshtml
+
+
+ AccountController.cs
+ /App_Code
+ AccountController.cs
+
+
+ ContactController.cs
+ /App_Code
+ ContactController.cs
+
+
+ LuceneHighlightHelper.cs
+ /App_Code
+ LuceneHighlightHelper.cs
+
+
+ default.js
+ /scripts
+ default.js
+
+
+ jquery.timers.js
+ /scripts
+ jquery.timers.js
+
+
+ Creative_Founds_Square.jpg
+ /images
+ Creative_Founds_Square.jpg
+
+
+ header_bg.png
+ /images
+ header_bg.png
+
+
+ li_bg.gif
+ /images
+ li_bg.gif
+
+
+ li_white_bg.gif
+ /images
+ li_white_bg.gif
+
+
+ logo.png
+ /images
+ logo.png
+
+
+ nav_li_bg.png
+ /images
+ nav_li_bg.png
+
+
+ search_bg.png
+ /images
+ search_bg.png
+
+
+ search_btn_bg.png
+ /images
+ search_btn_bg.png
+
+
+ slider_bg.png
+ /images
+ slider_bg.png
+
+
+ twitter_square.png
+ /images
+ twitter_square.png
+
+
+ umbraco_Square.jpg
+ /images
+ umbraco_Square.jpg
+
+
+ web_applications.jpg
+ /images
+ web_applications.jpg
+
+
+ Lucene.Net.Contrib.Highlighter.dll
+ /bin
+ Lucene.Net.Contrib.Highlighter.dll
+
+
+ StandardWebsiteInstall.ascx.cs
+ /usercontrols
+ StandardWebsiteInstall.ascx.cs
+
+
+ Affiliations.cshtml
+ /Views/Partials
+ Affiliations.cshtml
+
+
+ ContactForm.cshtml
+ /Views/Partials
+ ContactForm.cshtml
+
+
+ ContentPanels.cshtml
+ /Views/Partials
+ ContentPanels.cshtml
+
+
+ LeftNavigation.cshtml
+ /Views/Partials
+ LeftNavigation.cshtml
+
+
+ LoginForm.cshtml
+ /Views/Partials
+ LoginForm.cshtml
+
+
+ dice.png
+ /media/1824
+ dice.png
+
+
+ dice_thumb.jpg
+ /media/1824
+ dice_thumb.jpg
+
+
+ cap.png
+ /media/1813
+ cap.png
+
+
+ cap_thumb.jpg
+ /media/1813
+ cap_thumb.jpg
+
+
+ chat.jpg
+ /media/2075
+ chat.jpg
+
+
+ chat_thumb.jpg
+ /media/2075
+ chat_thumb.jpg
+
+
+ umbraco_logo.png
+ /media/1477
+ umbraco_logo.png
+
+
+ umbraco_logo_thumb.jpg
+ /media/1477
+ umbraco_logo_thumb.jpg
+
+
+ StandardWebsiteInstall.ascx
+ /usercontrols
+ StandardWebsiteInstall.ascx
+
+
+
+
+ StandardWebsiteMVC
+ 2.0
+ MIT license
+ http://our.umbraco.org/projects/starter-kits/standard-website-mvc
+
+ 3
+ 0
+ 0
+
+
+
+ Chris Koiak
+ http://www.creativefounds.co.uk
+
+
+
+
+
+
+
+
+
+
+ Built by Creative Founds
+
Creative Founds design and build first class software solutions that deliver big results. We provide ASP.NET web and mobile applications, Umbraco development service & technical consultancy.
Umbraco the the leading ASP.NET open source CMS, under pinning over 150,000 websites. Our Certified Developers are experts in developing high performance and feature rich websites.
]]>
+
+
+ Contact Us
+
We'd love to hear how this package has helped you and how it can be improved. Get in touch on the project website or via twitter
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur dictum, nisi non gravida blandit, odio nulla ultrices orci, quis blandit tortor libero vitae massa. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla at velit lacus.
+
Vivamus dictum, lorem vitae bold text, libero link text elit, vitae tincidunt ante nibh vitae lectus. Praesent molestie justo non mi dapibus et venenatis ante facilisis. Morbi gravida molestie cursus.
+
Sub Section
+
Aliquam at est dui. Pellentesque tortor risus, congue eget pretium ut, elementum eu velit. Phasellus tempus leo sed elit tempus vestibulum. Integer mollis arcu porta leo vulputate dignissim.
+
+
List Item 1
+
List Item 2
+
List Item 3
+
+
+
Numbered Item 1
+
Numbered Item 2
+
Numbered Item 3
+
+
In suscipit lectus vitae nibh faucibus vel lobortis est ullamcorper. Morbi risus nisl, sodales egestas placerat nec, cursus vel tellus. Vivamus aliquet sagittis pellentesque. Nulla rutrum neque nec metus mattis volutpat.
+
Vivamus egestas enim sed augue eleifend id tristique magna tempus. Nunc ullamcorper scelerisque ante quis consectetur.
+
Curabitur vel dui a enim adipiscing malesuada non quis velit.
Aliquam erat volutpat. Sed laoreet leo id nisi convallis sollicitudin sodales orci adipiscing. Sed a dolor ipsum. Quisque ut quam eu arcu placerat rhoncus vel et mi. Pellentesque sed est nisl.
+
Aliquam at orci justo, id pharetra augue. Aenean ut nunc ut nibh interdum scelerisque ut ac mi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vehicula dictum lectus in interdum. Fusce pellentesque elit nec metus convallis id porttitor felis laoreet. Nunc vitae enim quam.
]]>
+
+
+
+
+
+ 0
+
+
+
+
+ Clients
+
This is a standard content page.
+
Vestibulum malesuada aliquet ante, vitae ullamcorper felis faucibus vel. Vestibulum condimentum faucibus tellus porta ultrices. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
+
Cras at auctor orci. Praesent facilisis erat nec odio consequat at posuere ligula pretium. Nulla eget felis id nisl volutpat pellentesque. Ut id augue id ligula placerat rutrum a nec purus. Maecenas sed lectus ac mi pellentesque luctus quis sit amet turpis. Vestibulum adipiscing convallis vestibulum.
+
Duis condimentum lectus at orci placerat vitae imperdiet lorem cursus. Duis hendrerit porta lorem, non suscipit quam consectetur vitae. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean elit augue, tincidunt nec tincidunt id, elementum vel est.
]]>
+
+
+
+
+
+ 0
+
+
+ chriskoiak@gmail.com
+ Standard Website Contact Form
+ 1124
+ chriskoiak@gmail.com
+
+ Contact Us
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur dictum, nisi non gravida blandit, odio nulla ultrices orci, quis blandit tortor libero vitae massa.
Well hello! This website package demonstrates all the standard functionality of Umbraco. It's a great starting point for starting point for further development or as a prototype.