Migrated Umbraco.TestData to .NET 5.

This commit is contained in:
Andy Butland
2021-07-26 09:32:08 +02:00
parent 32e11ec8dc
commit 5bd00c8fc9
11 changed files with 354 additions and 364 deletions

View File

@@ -0,0 +1,16 @@
namespace Umbraco.TestData.Configuration
{
public class TestDataSettings
{
/// <summary>
/// Gets or sets a value indicating whether the test data generation is enabled.
/// </summary>
public bool Enabled { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether persisted local database cache files for content and media are disabled.
/// </summary>
/// <value>The URL path.</value>
public bool IgnoreLocalDb { get; set; } = false;
}
}

View File

@@ -0,0 +1,54 @@
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Infrastructure.PublishedCache;
using Umbraco.Cms.Web.Common.ApplicationBuilder;
using Umbraco.TestData.Configuration;
namespace Umbraco.TestData.Extensions
{
public static class UmbracoBuilderExtensions
{
public static IUmbracoBuilder AddUmbracoTestData(this IUmbracoBuilder builder)
{
if (builder.Services.Any(x => x.ServiceType == typeof(LoadTestController)))
{
// We assume forms are composed if any implementations of LoadTestController exists
return builder;
}
IConfigurationSection testDataSection = builder.Config.GetSection("Umbraco:CMS:TestData");
TestDataSettings config = testDataSection.Get<TestDataSettings>();
if (config == null || config.Enabled == false)
{
return builder;
}
builder.Services.Configure<TestDataSettings>(testDataSection);
if (config.IgnoreLocalDb)
{
builder.Services.AddSingleton(factory => new PublishedSnapshotServiceOptions
{
IgnoreLocalDb = true
});
}
builder.Services.Configure<UmbracoPipelineOptions>(options =>
options.AddFilter(new UmbracoPipelineFilter(nameof(LoadTestController))
{
Endpoints = app => app.UseEndpoints(endpoints =>
endpoints.MapControllerRoute(
"LoadTest",
"/LoadTest/{action}",
new { controller = "LoadTest", Action = "Index" }))
}));
builder.Services.AddScoped(typeof(LoadTestController));
return builder;
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Web.Mvc;
using System.Web.Routing;
using System.Configuration;
using Umbraco.Cms.Core.Composing;
// see https://github.com/Shazwazza/UmbracoScripts/tree/master/src/LoadTesting
namespace Umbraco.TestData
{
public class LoadTestComponent : IComponent
{
public void Initialize()
{
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
return;
RouteTable.Routes.MapRoute(
name: "LoadTest",
url: "LoadTest/{action}",
defaults: new
{
controller = "LoadTest",
action = "Index"
},
namespaces: new[] { "Umbraco.TestData" }
);
}
public void Terminate()
{
}
}
}

View File

@@ -1,31 +1,13 @@
using System.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Infrastructure.PublishedCache;
using Umbraco.TestData.Extensions;
// see https://github.com/Shazwazza/UmbracoScripts/tree/master/src/LoadTesting
namespace Umbraco.TestData
{
public class LoadTestComposer : ComponentComposer<LoadTestComponent>, IUserComposer
public class LoadTestComposer : IUserComposer
{
public override void Compose(IUmbracoBuilder builder)
{
base.Compose(builder);
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
return;
builder.Services.AddScoped(typeof(LoadTestController), typeof(LoadTestController));
if (ConfigurationManager.AppSettings["Umbraco.TestData.IgnoreLocalDb"] == "true")
{
builder.Services.AddSingleton(factory => new PublishedSnapshotServiceOptions
{
IgnoreLocalDb = true
});
}
}
public void Compose(IUmbracoBuilder builder) => builder.AddUmbracoTestData();
}
}

View File

@@ -1,21 +1,15 @@
using System;
using System.Configuration;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using System.IO;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Hosting;
// see https://github.com/Shazwazza/UmbracoScripts/tree/master/src/LoadTesting
@@ -23,27 +17,17 @@ namespace Umbraco.TestData
{
public class LoadTestController : Controller
{
public LoadTestController(
ServiceContext serviceContext,
IShortStringHelper shortStringHelper,
IHostingEnvironment hostingEnvironment)
{
_serviceContext = serviceContext;
_shortStringHelper = shortStringHelper;
_hostingEnvironment = hostingEnvironment;
}
private static readonly Random s_random = new Random();
private static readonly object s_locko = new object();
private static readonly Random _random = new Random();
private static readonly object _locko = new object();
private static volatile int s_containerId = -1;
private static volatile int _containerId = -1;
private const string ContainerAlias = "LoadTestContainer";
private const string ContentAlias = "LoadTestContent";
private const int TextboxDefinitionId = -88;
private const int MaxCreate = 1000;
private const string _containerAlias = "LoadTestContainer";
private const string _contentAlias = "LoadTestContent";
private const int _textboxDefinitionId = -88;
private const int _maxCreate = 1000;
private static readonly string HeadHtml = @"<html>
private static readonly string s_headHtml = @"<html>
<head>
<title>LoadTest</title>
<style>
@@ -67,18 +51,18 @@ namespace Umbraco.TestData
private const string FootHtml = @"</body>
</html>";
private static readonly string _containerTemplateText = @"
private static readonly string s_containerTemplateText = @"
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@{
Layout = null;
var container = Umbraco.ContentAtRoot().OfTypes(""" + _containerAlias + @""").FirstOrDefault();
var container = Umbraco.ContentAtRoot().OfTypes(""" + ContainerAlias + @""").FirstOrDefault();
var contents = container.Children().ToArray();
var groups = contents.GroupBy(x => x.Value<string>(""origin""));
var id = contents.Length > 0 ? contents[0].Id : -1;
var wurl = Request.QueryString[""u""] == ""1"";
var missing = contents.Length > 0 && contents[contents.Length - 1].Id - contents[0].Id >= contents.Length;
}
" + HeadHtml + @"
" + s_headHtml + @"
<div class=""block"">
<span @Html.Raw(missing ? ""style=\""color:red;\"""" : """")>@contents.Length items</span>
<ul>
@@ -106,19 +90,41 @@ namespace Umbraco.TestData
}
</div>
" + FootHtml;
private readonly ServiceContext _serviceContext;
private readonly IShortStringHelper _shortStringHelper;
private readonly IHostingEnvironment _hostingEnvironment;
private ActionResult ContentHtml(string s)
private readonly IContentTypeService _contentTypeService;
private readonly IContentService _contentService;
private readonly IDataTypeService _dataTypeService;
private readonly IFileService _fileService;
private readonly IShortStringHelper _shortStringHelper;
private readonly Cms.Core.Hosting.IHostingEnvironment _hostingEnvironment;
private readonly IHostApplicationLifetime _hostApplicationLifetime;
public LoadTestController(
IContentTypeService contentTypeService,
IContentService contentService,
IDataTypeService dataTypeService,
IFileService fileService,
IShortStringHelper shortStringHelper,
Cms.Core.Hosting.IHostingEnvironment hostingEnvironment,
IHostApplicationLifetime hostApplicationLifetime)
{
return Content(HeadHtml + s + FootHtml);
_contentTypeService = contentTypeService;
_contentService = contentService;
_dataTypeService = dataTypeService;
_fileService = fileService;
_shortStringHelper = shortStringHelper;
_hostingEnvironment = hostingEnvironment;
_hostApplicationLifetime = hostApplicationLifetime;
}
public ActionResult Index()
public IActionResult Index()
{
var res = EnsureInitialize();
if (res != null) return res;
IActionResult res = EnsureInitialize();
if (res != null)
{
return res;
}
var html = @"Welcome. You can:
<ul>
@@ -135,68 +141,71 @@ namespace Umbraco.TestData
return ContentHtml(html);
}
private ActionResult EnsureInitialize()
private IActionResult EnsureInitialize()
{
if (_containerId > 0) return null;
lock (_locko)
if (s_containerId > 0)
{
if (_containerId > 0) return null;
return null;
}
var contentTypeService = _serviceContext.ContentTypeService;
var contentType = contentTypeService.Get(_contentAlias);
lock (s_locko)
{
if (s_containerId > 0)
{
return null;
}
IContentType contentType = _contentTypeService.Get(ContentAlias);
if (contentType == null)
{
return ContentHtml("Not installed, first you must <a href=\"/LoadTest/Install\">install</a>.");
}
var containerType = contentTypeService.Get(_containerAlias);
IContentType containerType = _contentTypeService.Get(ContainerAlias);
if (containerType == null)
{
return ContentHtml("Panic! Container type is missing.");
}
var contentService = _serviceContext.ContentService;
var container = contentService.GetPagedOfType(containerType.Id, 0, 100, out _, null).FirstOrDefault();
IContent container = _contentService.GetPagedOfType(containerType.Id, 0, 100, out _, null).FirstOrDefault();
if (container == null)
{
return ContentHtml("Panic! Container is missing.");
}
_containerId = container.Id;
s_containerId = container.Id;
return null;
}
}
public ActionResult Install()
private IActionResult ContentHtml(string s) => Content(s_headHtml + s + FootHtml);
public IActionResult Install()
{
var dataTypeService = _serviceContext.DataTypeService;
//var dataType = dataTypeService.GetAll(Constants.DataTypes.DefaultContentListView);
//if (!dict.ContainsKey("pageSize")) dict["pageSize"] = new PreValue("10");
//dict["pageSize"].Value = "200";
//dataTypeService.SavePreValues(dataType, dict);
var contentTypeService = _serviceContext.ContentTypeService;
var contentType = new ContentType(_shortStringHelper, -1)
{
Alias = _contentAlias,
Alias = ContentAlias,
Name = "LoadTest Content",
Description = "Content for LoadTest",
Icon = "icon-document"
};
var def = _serviceContext.DataTypeService.GetDataType(_textboxDefinitionId);
IDataType def = _dataTypeService.GetDataType(TextboxDefinitionId);
contentType.AddPropertyType(new PropertyType(_shortStringHelper, def)
{
Name = "Origin",
Alias = "origin",
Description = "The origin of the content.",
});
contentTypeService.Save(contentType);
_contentTypeService.Save(contentType);
var containerTemplate = ImportTemplate(_serviceContext, _shortStringHelper,
"LoadTestContainer", "LoadTestContainer", _containerTemplateText);
Template containerTemplate = ImportTemplate(
"LoadTestContainer",
"LoadTestContainer",
s_containerTemplateText);
var containerType = new ContentType(_shortStringHelper, -1)
{
Alias = _containerAlias,
Alias = ContainerAlias,
Name = "LoadTest Container",
Description = "Container for LoadTest content",
Icon = "icon-document",
@@ -209,59 +218,92 @@ namespace Umbraco.TestData
});
containerType.AllowedTemplates = containerType.AllowedTemplates.Union(new[] { containerTemplate });
containerType.SetDefaultTemplate(containerTemplate);
contentTypeService.Save(containerType);
_contentTypeService.Save(containerType);
var contentService = _serviceContext.ContentService;
var content = contentService.Create("LoadTestContainer", -1, _containerAlias);
contentService.SaveAndPublish(content);
IContent content = _contentService.Create("LoadTestContainer", -1, ContainerAlias);
_contentService.SaveAndPublish(content);
return ContentHtml("Installed.");
}
public ActionResult Create(int n = 1, int r = 0, string o = null)
private Template ImportTemplate(string name, string alias, string text, ITemplate master = null)
{
var res = EnsureInitialize();
if (res != null) return res;
var t = new Template(_shortStringHelper, name, alias) { Content = text };
if (master != null)
{
t.SetMasterTemplate(master);
}
_fileService.SaveTemplate(t);
return t;
}
public IActionResult Create(int n = 1, int r = 0, string o = null)
{
IActionResult res = EnsureInitialize();
if (res != null)
{
return res;
}
if (r < 0)
{
r = 0;
}
if (r > 100)
{
r = 100;
}
if (r < 0) r = 0;
if (r > 100) r = 100;
var restart = GetRandom(0, 100) > (100 - r);
var contentService = _serviceContext.ContentService;
if (n < 1)
{
n = 1;
}
if (n > MaxCreate)
{
n = MaxCreate;
}
if (n < 1) n = 1;
if (n > _maxCreate) n = _maxCreate;
for (int i = 0; i < n; i++)
{
var name = Guid.NewGuid().ToString("N").ToUpper() + "-" + (restart ? "R" : "X") + "-" + o;
var content = contentService.Create(name, _containerId, _contentAlias);
IContent content = _contentService.Create(name, s_containerId, ContentAlias);
content.SetValue("origin", o);
contentService.SaveAndPublish(content);
_contentService.SaveAndPublish(content);
}
if (restart)
{
DoRestart();
}
return ContentHtml("Created " + n + " content"
+ (restart ? ", and restarted" : "")
+ ".");
}
private int GetRandom(int minValue, int maxValue)
private static int GetRandom(int minValue, int maxValue)
{
lock (_locko)
lock (s_locko)
{
return _random.Next(minValue, maxValue);
return s_random.Next(minValue, maxValue);
}
}
public ActionResult Clear()
public IActionResult Clear()
{
var res = EnsureInitialize();
if (res != null) return res;
IActionResult res = EnsureInitialize();
if (res != null)
{
return res;
}
var contentType = _serviceContext.ContentTypeService.Get(_contentAlias);
_serviceContext.ContentService.DeleteOfType(contentType.Id);
IContentType contentType = _contentTypeService.Get(ContentAlias);
_contentService.DeleteOfType(contentType.Id);
return ContentHtml("Cleared.");
}
@@ -269,12 +311,11 @@ namespace Umbraco.TestData
private void DoRestart()
{
HttpContext.User = null;
System.Web.HttpContext.Current.User = null;
Thread.CurrentPrincipal = null;
HttpRuntime.UnloadAppDomain();
_hostApplicationLifetime.StopApplication();
}
public ActionResult ColdBootRestart()
public IActionResult ColdBootRestart()
{
Directory.Delete(_hostingEnvironment.MapPathContentRoot(Path.Combine(Constants.SystemDirectories.TempData,"DistCache")), true);
@@ -283,35 +324,38 @@ namespace Umbraco.TestData
return Content("Cold Boot Restarted.");
}
public ActionResult Restart()
public IActionResult Restart()
{
DoRestart();
return ContentHtml("Restarted.");
}
public ActionResult Die()
public IActionResult Die()
{
var timer = new System.Threading.Timer(_ =>
{
throw new Exception("die!");
});
timer.Change(100, 0);
var timer = new Timer(_ => throw new Exception("die!"));
_ = timer.Change(100, 0);
return ContentHtml("Dying.");
}
public ActionResult Domains()
public IActionResult Domains()
{
var currentDomain = AppDomain.CurrentDomain;
AppDomain currentDomain = AppDomain.CurrentDomain;
var currentName = currentDomain.FriendlyName;
var pos = currentName.IndexOf('-');
if (pos > 0) currentName = currentName.Substring(0, pos);
if (pos > 0)
{
currentName = currentName.Substring(0, pos);
}
var text = new System.Text.StringBuilder();
var text = new StringBuilder();
text.Append("<div class=\"block\">Process ID: " + Process.GetCurrentProcess().Id + "</div>");
text.Append("<div class=\"block\">");
text.Append("<div>IIS Site: " + HostingEnvironment.ApplicationHost.GetSiteName() + "</div>");
// TODO (V9): Commented out as I assume not available?
////text.Append("<div>IIS Site: " + HostingEnvironment.ApplicationHost.GetSiteName() + "</div>");
text.Append("<div>App ID: " + currentName + "</div>");
//text.Append("<div>AppPool: " + Zbu.WebManagement.AppPoolHelper.GetCurrentApplicationPoolName() + "</div>");
text.Append("</div>");
@@ -338,56 +382,5 @@ namespace Umbraco.TestData
return ContentHtml(text.ToString());
}
public ActionResult Recycle()
{
return ContentHtml("Not implemented&mdash;please use IIS console.");
}
private static Template ImportTemplate(ServiceContext svces, IShortStringHelper shortStringHelper, string name, string alias, string text, ITemplate master = null)
{
var t = new Template(shortStringHelper, name, alias) { Content = text };
if (master != null)
t.SetMasterTemplate(master);
svces.FileService.SaveTemplate(t);
return t;
}
}
public class TestComponent : IComponent
{
public void Initialize()
{
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
return;
RouteTable.Routes.MapRoute(
name: "LoadTest",
url: "LoadTest/{action}",
defaults: new
{
controller = "LoadTest",
action = "Index"
},
namespaces: new[] { "Umbraco.TestData" }
);
}
public void Terminate()
{
}
}
public class TestComposer : ComponentComposer<TestComponent>, IUserComposer
{
public override void Compose(IUmbracoBuilder builder)
{
base.Compose(builder);
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
return;
builder.Services.AddScoped(typeof(LoadTestController));
}
}
}

View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Umbraco.TestData")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Umbraco.TestData")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("fb5676ed-7a69-492c-b802-e7b24144c0fc")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,31 +1,55 @@
using System.Configuration;
using System;
using System.Configuration;
using System.Linq;
using System.Web.Mvc;
using Umbraco.Cms.Core;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Web.Website.Controllers;
using Umbraco.Extensions;
using Umbraco.Web.Mvc;
namespace Umbraco.TestData
{
public class SegmentTestController : SurfaceController
{
public SegmentTestController(
IUmbracoContextAccessor umbracoContextAccessor,
IUmbracoDatabaseFactory databaseFactory,
ServiceContext services,
AppCaches appCaches,
IProfilingLogger profilingLogger,
IPublishedUrlProvider publishedUrlProvider)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
{
}
public ActionResult EnableDocTypeSegments(string alias, string propertyTypeAlias)
public IActionResult EnableDocTypeSegments(string alias, string propertyTypeAlias)
{
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
{
return HttpNotFound();
}
var ct = Services.ContentTypeService.Get(alias);
IContentType ct = Services.ContentTypeService.Get(alias);
if (ct == null)
{
return Content($"No document type found by alias {alias}");
}
var propType = ct.PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias);
IPropertyType propType = ct.PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias);
if (propType == null)
{
return Content($"The document type {alias} does not have a property type {propertyTypeAlias ?? "null"}");
}
if (ct.Variations.VariesBySegment())
{
return Content($"The document type {alias} already allows segments, nothing has been changed");
}
ct.SetVariesBy(ContentVariation.Segment);
propType.SetVariesBy(ContentVariation.Segment);
@@ -34,17 +58,25 @@ namespace Umbraco.TestData
return Content($"The document type {alias} and property type {propertyTypeAlias} now allows segments");
}
public ActionResult DisableDocTypeSegments(string alias)
private IActionResult HttpNotFound() => throw new NotImplementedException();
public IActionResult DisableDocTypeSegments(string alias)
{
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
{
return HttpNotFound();
}
var ct = Services.ContentTypeService.Get(alias);
IContentType ct = Services.ContentTypeService.Get(alias);
if (ct == null)
{
return Content($"No document type found by alias {alias}");
}
if (!ct.VariesBySegment())
{
return Content($"The document type {alias} does not allow segments, nothing has been changed");
}
ct.SetVariesBy(ContentVariation.Segment, false);
@@ -54,21 +86,31 @@ namespace Umbraco.TestData
public ActionResult AddSegmentData(int contentId, string propertyAlias, string value, string segment, string culture = null)
{
var content = Services.ContentService.GetById(contentId);
IContent content = Services.ContentService.GetById(contentId);
if (content == null)
{
return Content($"No content found by id {contentId}");
}
if (propertyAlias.IsNullOrWhiteSpace() || !content.HasProperty(propertyAlias))
{
return Content($"The content by id {contentId} does not contain a property with alias {propertyAlias ?? "null"}");
}
if (content.ContentType.VariesByCulture() && culture.IsNullOrWhiteSpace())
{
return Content($"The content by id {contentId} varies by culture but no culture was specified");
}
if (value.IsNullOrWhiteSpace())
{
return Content("'value' cannot be null");
}
if (segment.IsNullOrWhiteSpace())
{
return Content("'segment' cannot be null");
}
content.SetValue(propertyAlias, value, culture, segment);
Services.ContentService.Save(content);

View File

@@ -1,82 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FB5676ED-7A69-492C-B802-E7B24144C0FC}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<IsPackable>false</IsPackable>
<RootNamespace>Umbraco.TestData</RootNamespace>
<AssemblyName>Umbraco.TestData</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<LangVersion>8</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<PackageReference Include="Bogus" Version="33.0.2" />
</ItemGroup>
<ItemGroup>
<Compile Include="LoadTestComponent.cs" />
<Compile Include="LoadTestComposer.cs" />
<Compile Include="LoadTestController.cs" />
<Compile Include="SegmentTestController.cs" />
<Compile Include="UmbracoTestDataController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
<ProjectReference Include="..\Umbraco.PublishedCache.NuCache\Umbraco.PublishedCache.NuCache.csproj" />
<ProjectReference Include="..\Umbraco.Web.Common\Umbraco.Web.Common.csproj" />
<ProjectReference Include="..\Umbraco.Web.Website\Umbraco.Web.Website.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="readme.md" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
<Project>{29aa69d9-b597-4395-8d42-43b1263c240a}</Project>
<Name>Umbraco.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Infrastructure\Umbraco.Infrastructure.csproj">
<Project>{3ae7bf57-966b-45a5-910a-954d7c554441}</Project>
<Name>Umbraco.Infrastructure</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.PublishedCache.NuCache\Umbraco.PublishedCache.NuCache.csproj">
<Project>{f6de8da0-07cc-4ef2-8a59-2bc81dbb3830}</Project>
<Name>Umbraco.PublishedCache.NuCache</Name>
</ProjectReference>
<ProjectReference Include="..\Umbraco.Web\Umbraco.Web.csproj">
<Project>{651e1350-91b6-44b7-bd60-7207006d7003}</Project>
<Name>Umbraco.Web</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Bogus">
<Version>33.0.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNet.Mvc">
<Version>5.2.7</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>

View File

@@ -1,22 +1,24 @@
using System;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.Mvc;
using Bogus;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Infrastructure.Serialization;
using Umbraco.Cms.Web.Website.Controllers;
using Umbraco.Extensions;
using Umbraco.Web.Mvc;
using Umbraco.TestData.Configuration;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.TestData
@@ -33,13 +35,25 @@ namespace Umbraco.TestData
private readonly IScopeProvider _scopeProvider;
private readonly PropertyEditorCollection _propertyEditors;
private readonly IShortStringHelper _shortStringHelper;
private readonly TestDataSettings _testDataSettings;
public UmbracoTestDataController(IScopeProvider scopeProvider, PropertyEditorCollection propertyEditors, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IShortStringHelper shortStringHelper)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger)
public UmbracoTestDataController(
IUmbracoContextAccessor umbracoContextAccessor,
IUmbracoDatabaseFactory databaseFactory,
ServiceContext services,
AppCaches appCaches,
IProfilingLogger profilingLogger,
IPublishedUrlProvider publishedUrlProvider,
IScopeProvider scopeProvider,
PropertyEditorCollection propertyEditors,
IShortStringHelper shortStringHelper,
IOptions<TestDataSettings> testDataSettings)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
{
_scopeProvider = scopeProvider;
_propertyEditors = propertyEditors;
_shortStringHelper = shortStringHelper;
_testDataSettings = testDataSettings.Value;
}
/// <summary>
@@ -52,18 +66,22 @@ namespace Umbraco.TestData
/// <remarks>
/// Each content item created is associated to a media item via a media picker and therefore a relation is created between the two
/// </remarks>
public ActionResult CreateTree(int count, int depth, string locale = "en")
public IActionResult CreateTree(int count, int depth, string locale = "en")
{
if (ConfigurationManager.AppSettings["Umbraco.TestData.Enabled"] != "true")
return HttpNotFound();
if (_testDataSettings.Enabled == false)
{
return NotFound();
}
if (!Validate(count, depth, out var message, out var perLevel))
{
throw new InvalidOperationException(message);
}
var faker = new Faker(locale);
var company = faker.Company.CompanyName();
using (var scope = _scopeProvider.CreateScope())
using (IScope scope = _scopeProvider.CreateScope())
{
var imageIds = CreateMediaTree(company, faker, count, depth).ToList();
var contentIds = CreateContentTree(company, faker, count, depth, imageIds, out var root).ToList();
@@ -77,7 +95,7 @@ namespace Umbraco.TestData
return Content("Done");
}
private bool Validate(int count, int depth, out string message, out int perLevel)
private static bool Validate(int count, int depth, out string message, out int perLevel)
{
perLevel = 0;
message = null;
@@ -128,8 +146,8 @@ namespace Umbraco.TestData
for (int i = 0; i < count; i++)
{
var created = create(parent);
var contentItem = created.content;
(T content, Func<T> container) created = create(parent);
T contentItem = created.content;
yield return contentItem.GetUdi();
@@ -139,7 +157,7 @@ namespace Umbraco.TestData
{
// move back up...
var prev = tracked.Pop();
(T parent, int childCount) prev = tracked.Pop();
// restore child count
currChildCount = prev.childCount;
@@ -171,7 +189,7 @@ namespace Umbraco.TestData
/// <returns></returns>
private IEnumerable<Udi> CreateMediaTree(string company, Faker faker, int count, int depth)
{
var parent = Services.MediaService.CreateMediaWithIdentity(company, -1, Constants.Conventions.MediaTypes.Folder);
IMedia parent = Services.MediaService.CreateMediaWithIdentity(company, -1, Constants.Conventions.MediaTypes.Folder);
return CreateHierarchy(parent, count, depth, currParent =>
{
@@ -185,13 +203,13 @@ namespace Umbraco.TestData
// if we don't do this we don't get thumbnails in the back office.
imageUrl += "&ext=.jpg";
var media = Services.MediaService.CreateMedia(faker.Commerce.ProductName(), currParent, Constants.Conventions.MediaTypes.Image);
IMedia media = Services.MediaService.CreateMedia(faker.Commerce.ProductName(), currParent, Constants.Conventions.MediaTypes.Image);
media.SetValue(Constants.Conventions.Media.File, imageUrl);
Services.MediaService.Save(media);
return (media, () =>
{
// create a folder to contain child media
var container = Services.MediaService.CreateMediaWithIdentity(faker.Commerce.Department(), currParent, Constants.Conventions.MediaTypes.Folder);
IMedia container = Services.MediaService.CreateMediaWithIdentity(faker.Commerce.Department(), currParent, Constants.Conventions.MediaTypes.Folder);
return container;
});
});
@@ -210,9 +228,10 @@ namespace Umbraco.TestData
{
var random = new Random(company.GetHashCode());
var docType = GetOrCreateContentType();
IContentType docType = GetOrCreateContentType();
IContent parent = Services.ContentService.Create(company, -1, docType.Alias);
var parent = Services.ContentService.Create(company, -1, docType.Alias);
// give it some reasonable data (100 reviews)
parent.SetValue("review", string.Join(" ", Enumerable.Range(0, 100).Select(x => faker.Rant.Review())));
parent.SetValue("desc", company);
@@ -223,7 +242,8 @@ namespace Umbraco.TestData
return CreateHierarchy(parent, count, depth, currParent =>
{
var content = Services.ContentService.Create(faker.Commerce.ProductName(), currParent, docType.Alias);
IContent content = Services.ContentService.Create(faker.Commerce.ProductName(), currParent, docType.Alias);
// give it some reasonable data (100 reviews)
content.SetValue("review", string.Join(" ", Enumerable.Range(0, 100).Select(x => faker.Rant.Review())));
content.SetValue("desc", string.Join(", ", Enumerable.Range(0, 5).Select(x => faker.Commerce.ProductAdjective())));
@@ -237,9 +257,11 @@ namespace Umbraco.TestData
private IContentType GetOrCreateContentType()
{
var docType = Services.ContentTypeService.Get(TestDataContentTypeAlias);
IContentType docType = Services.ContentTypeService.Get(TestDataContentTypeAlias);
if (docType != null)
{
return docType;
}
docType = new ContentType(_shortStringHelper, -1)
{
@@ -274,12 +296,17 @@ namespace Umbraco.TestData
private IDataType GetOrCreateDataType(string name, string editorAlias)
{
var dt = Services.DataTypeService.GetDataType(name);
if (dt != null) return dt;
IDataType dt = Services.DataTypeService.GetDataType(name);
if (dt != null)
{
return dt;
}
var editor = _propertyEditors.FirstOrDefault(x => x.Alias == editorAlias);
IDataEditor editor = _propertyEditors.FirstOrDefault(x => x.Alias == editorAlias);
if (editor == null)
{
throw new InvalidOperationException($"No {editorAlias} editor found");
}
var serializer = new ConfigurationEditorJsonSerializer();

View File

@@ -1,9 +1,9 @@
## Umbraco Test Data
## Umbraco Test Data
This project is a utility to be able to generate large amounts of content and media in an
Umbraco installation for testing.
Currently this project is referenced in the Umbraco.Web.UI project but only when it's being built
Currently this project is referenced in the Umbraco.Web.UI.NetCore project but only when it's being built
in Debug mode (i.e. when testing within Visual Studio).
## Usage
@@ -12,8 +12,16 @@ You must use SQL Server for this, using SQLCE will die if you try to bulk create
It has to be enabled by an appSetting:
```xml
<add key="Umbraco.TestData.Enabled" value="true"/>
```json
{
"Umbraco": {
"CMS": {
"TestData": {
"Enabled" : true,
}
}
}
}
```
Once this is enabled this endpoint can be executed:

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
@@ -16,6 +16,7 @@
<ProjectReference Include="../Umbraco.Web.Common/Umbraco.Web.Common.csproj" />
<ProjectReference Include="../Umbraco.Web.Website/Umbraco.Web.Website.csproj" />
<ProjectReference Include="../Umbraco.Persistence.SqlCe/Umbraco.Persistence.SqlCe.csproj" Condition="'$(OS)' == 'Windows_NT'" />
<ProjectReference Include="../Umbraco.TestData/Umbraco.TestData.csproj" Condition="'$(Configuration)' == 'Debug'" />
</ItemGroup>
<ItemGroup>