Merge remote-tracking branch 'origin/netcore/dev' into netcore/feature/AB3594_move_exsiting_configuration_to_own_project
This commit is contained in:
@@ -39,29 +39,6 @@ namespace Umbraco.Core
|
||||
Guid = guid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent GuidUdi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <returns>A GuidUdi instance that contains the value that was parsed.</returns>
|
||||
public new static GuidUdi Parse(string s)
|
||||
{
|
||||
var udi = Udi.Parse(s);
|
||||
if (udi is GuidUdi == false)
|
||||
throw new FormatException("String \"" + s + "\" is not a guid entity id.");
|
||||
|
||||
return (GuidUdi) udi;
|
||||
}
|
||||
|
||||
public static bool TryParse(string s, out GuidUdi udi)
|
||||
{
|
||||
Udi tmp;
|
||||
udi = null;
|
||||
if (TryParse(s, out tmp) == false) return false;
|
||||
udi = tmp as GuidUdi;
|
||||
return udi != null;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as GuidUdi;
|
||||
@@ -49,29 +49,6 @@ namespace Umbraco.Core
|
||||
return string.Join("/", s.Split('/').Select(Uri.EscapeDataString));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent StringUdi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <returns>A StringUdi instance that contains the value that was parsed.</returns>
|
||||
public new static StringUdi Parse(string s)
|
||||
{
|
||||
var udi = Udi.Parse(s);
|
||||
if (udi is StringUdi == false)
|
||||
throw new FormatException("String \"" + s + "\" is not a string entity id.");
|
||||
|
||||
return (StringUdi) udi;
|
||||
}
|
||||
|
||||
public static bool TryParse(string s, out StringUdi udi)
|
||||
{
|
||||
udi = null;
|
||||
Udi tmp;
|
||||
if (TryParse(s, out tmp) == false || tmp is StringUdi == false) return false;
|
||||
udi = (StringUdi) tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsRoot
|
||||
{
|
||||
171
src/Umbraco.Abstractions/Udi.cs
Normal file
171
src/Umbraco.Abstractions/Udi.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entity identifier.
|
||||
/// </summary>
|
||||
/// <remarks>An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document.</remarks>
|
||||
[TypeConverter(typeof(UdiTypeConverter))]
|
||||
public abstract class Udi : IComparable<Udi>
|
||||
{
|
||||
public Uri UriValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Udi class.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type part of the identifier.</param>
|
||||
/// <param name="stringValue">The string value of the identifier.</param>
|
||||
protected Udi(string entityType, string stringValue)
|
||||
{
|
||||
EntityType = entityType;
|
||||
UriValue = new Uri(stringValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Udi class.
|
||||
/// </summary>
|
||||
/// <param name="uriValue">The uri value of the identifier.</param>
|
||||
protected Udi(Uri uriValue)
|
||||
{
|
||||
EntityType = uriValue.Host;
|
||||
UriValue = uriValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entity type part of the identifier.
|
||||
/// </summary>
|
||||
public string EntityType { get; private set; }
|
||||
|
||||
public int CompareTo(Udi other)
|
||||
{
|
||||
return string.Compare(UriValue.ToString(), other.UriValue.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// UriValue is created in the ctor and is never null
|
||||
// use AbsoluteUri here and not ToString else it's not encoded!
|
||||
return UriValue.AbsoluteUri;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a root Udi for an entity type.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <returns>The root Udi for the entity type.</returns>
|
||||
public static Udi Create(string entityType)
|
||||
{
|
||||
return UdiParser.GetRootUdi(entityType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a string Udi.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>The string Udi for the entity type and identifier.</returns>
|
||||
public static Udi Create(string entityType, string id)
|
||||
{
|
||||
if (UdiParser.UdiTypes.TryGetValue(entityType, out var udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
throw new ArgumentException("Value cannot be null or whitespace.", "id");
|
||||
if (udiType != UdiType.StringUdi)
|
||||
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have string udis.", entityType));
|
||||
|
||||
return new StringUdi(entityType, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Guid Udi.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>The Guid Udi for the entity type and identifier.</returns>
|
||||
public static Udi Create(string entityType, Guid id)
|
||||
{
|
||||
if (UdiParser.UdiTypes.TryGetValue(entityType, out var udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
|
||||
|
||||
if (udiType != UdiType.GuidUdi)
|
||||
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType));
|
||||
if (id == default(Guid))
|
||||
throw new ArgumentException("Cannot be an empty guid.", "id");
|
||||
|
||||
return new GuidUdi(entityType, id);
|
||||
}
|
||||
|
||||
public static Udi Create(Uri uri)
|
||||
{
|
||||
// if it's a know type go fast and use ctors
|
||||
// else fallback to parsing the string (and guess the type)
|
||||
|
||||
if (UdiParser.UdiTypes.TryGetValue(uri.Host, out var udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri");
|
||||
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
return new GuidUdi(uri);
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
return new StringUdi(uri);
|
||||
|
||||
throw new ArgumentException(string.Format("Uri \"{0}\" is not a valid udi.", uri));
|
||||
}
|
||||
|
||||
public void EnsureType(params string[] validTypes)
|
||||
{
|
||||
if (validTypes.Contains(EntityType) == false)
|
||||
throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this Udi is a root Udi.
|
||||
/// </summary>
|
||||
/// <remarks>A root Udi points to the "root of all things" for a given entity type, e.g. the content tree root.</remarks>
|
||||
public abstract bool IsRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that this Udi is not a root Udi.
|
||||
/// </summary>
|
||||
/// <returns>This Udi.</returns>
|
||||
/// <exception cref="Exception">When this Udi is a Root Udi.</exception>
|
||||
public Udi EnsureNotRoot()
|
||||
{
|
||||
if (IsRoot) throw new Exception("Root Udi.");
|
||||
return this;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as Udi;
|
||||
return other != null && GetType() == other.GetType() && UriValue == other.UriValue;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return UriValue.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(Udi udi1, Udi udi2)
|
||||
{
|
||||
if (ReferenceEquals(udi1, udi2)) return true;
|
||||
if ((object)udi1 == null || (object)udi2 == null) return false;
|
||||
return udi1.Equals(udi2);
|
||||
}
|
||||
|
||||
public static bool operator !=(Udi udi1, Udi udi2)
|
||||
{
|
||||
return (udi1 == udi2) == false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
222
src/Umbraco.Abstractions/UdiParser.cs
Normal file
222
src/Umbraco.Abstractions/UdiParser.cs
Normal file
@@ -0,0 +1,222 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public sealed class UdiParser
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, Udi> RootUdis = new ConcurrentDictionary<string, Udi>();
|
||||
internal static ConcurrentDictionary<string, UdiType> UdiTypes { get; private set; }
|
||||
|
||||
static UdiParser()
|
||||
{
|
||||
// initialize with known (built-in) Udi types
|
||||
// we will add scanned types later on
|
||||
UdiTypes = new ConcurrentDictionary<string, UdiType>(GetKnownUdiTypes());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal API for tests to resets all udi types back to only the known udi types.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static void ResetUdiTypes()
|
||||
{
|
||||
UdiTypes = new ConcurrentDictionary<string, UdiType>(GetKnownUdiTypes());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <returns>An Udi instance that contains the value that was parsed.</returns>
|
||||
public static Udi Parse(string s)
|
||||
{
|
||||
ParseInternal(s, false, false, out var udi);
|
||||
return udi;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
|
||||
/// <returns>An Udi instance that contains the value that was parsed.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
|
||||
/// the entity type was not known, the method succeeds but sets <c>udi</c>to an
|
||||
/// <see cref="UnknownTypeUdi"/> value.</para>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
|
||||
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
|
||||
/// </remarks>
|
||||
public static Udi Parse(string s, bool knownTypes)
|
||||
{
|
||||
ParseInternal(s, false, knownTypes, out var udi);
|
||||
return udi;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
|
||||
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
|
||||
public static bool TryParse(string s, out Udi udi)
|
||||
{
|
||||
return ParseInternal(s, true, false, out udi);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
|
||||
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
|
||||
public static bool TryParse<T>(string s, out T udi)
|
||||
where T : Udi
|
||||
{
|
||||
var result = ParseInternal(s, true, false, out var parsed);
|
||||
if (result && parsed is T)
|
||||
{
|
||||
udi = (T)parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
udi = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
|
||||
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
|
||||
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
|
||||
/// the entity type was not known, the method returns <c>false</c> but still sets <c>udi</c>
|
||||
/// to an <see cref="UnknownTypeUdi"/> value.</para>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
|
||||
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
|
||||
/// </remarks>
|
||||
public static bool TryParse(string s, bool knownTypes, out Udi udi)
|
||||
{
|
||||
return ParseInternal(s, true, knownTypes, out udi);
|
||||
}
|
||||
|
||||
private static bool ParseInternal(string s, bool tryParse, bool knownTypes, out Udi udi)
|
||||
{
|
||||
udi = null;
|
||||
Uri uri;
|
||||
|
||||
if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false
|
||||
|| Uri.TryCreate(s, UriKind.Absolute, out uri) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
|
||||
}
|
||||
|
||||
var entityType = uri.Host;
|
||||
if (UdiTypes.TryGetValue(entityType, out var udiType) == false)
|
||||
{
|
||||
if (knownTypes)
|
||||
{
|
||||
// not knowing the type is not an error
|
||||
// just return the unknown type udi
|
||||
udi = UnknownTypeUdi.Instance;
|
||||
return false;
|
||||
}
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("Unknown entity type \"{0}\".", entityType));
|
||||
}
|
||||
|
||||
var path = uri.AbsolutePath.TrimStart('/');
|
||||
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
{
|
||||
if (path == string.Empty)
|
||||
{
|
||||
udi = GetRootUdi(uri.Host);
|
||||
return true;
|
||||
}
|
||||
if (Guid.TryParse(path, out var guid) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
|
||||
}
|
||||
udi = new GuidUdi(uri.Host, guid);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (udiType == UdiType.StringUdi)
|
||||
{
|
||||
udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tryParse) return false;
|
||||
throw new InvalidOperationException(string.Format("Invalid udi type \"{0}\".", udiType));
|
||||
}
|
||||
|
||||
internal static Udi GetRootUdi(string entityType)
|
||||
{
|
||||
return RootUdis.GetOrAdd(entityType, x =>
|
||||
{
|
||||
if (UdiTypes.TryGetValue(x, out var udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType));
|
||||
return udiType == UdiType.StringUdi
|
||||
? (Udi)new StringUdi(entityType, string.Empty)
|
||||
: new GuidUdi(entityType, Guid.Empty);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Registers a custom entity type.
|
||||
/// </summary>
|
||||
/// <param name="entityType"></param>
|
||||
/// <param name="udiType"></param>
|
||||
public static void RegisterUdiType(string entityType, UdiType udiType) => UdiTypes.TryAdd(entityType, udiType);
|
||||
|
||||
public static Dictionary<string, UdiType> GetKnownUdiTypes() =>
|
||||
new Dictionary<string, UdiType>
|
||||
{
|
||||
{ Constants.UdiEntityType.Unknown, UdiType.Unknown },
|
||||
|
||||
{ Constants.UdiEntityType.AnyGuid, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Document, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentBlueprint, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Media, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Member, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DictionaryItem, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Macro, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Template, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentTypeContainer, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentTypeBluePrints, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MediaType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MediaTypeContainer, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DataType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DataTypeContainer, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MemberType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MemberGroup, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.RelationType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.FormsForm, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.FormsPreValue, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.FormsDataSource, UdiType.GuidUdi },
|
||||
|
||||
{ Constants.UdiEntityType.AnyString, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.Language, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.MacroScript, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.MediaFile, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.TemplateFile, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.Script, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.PartialView, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.PartialViewMacro, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.Stylesheet, UdiType.StringUdi }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core
|
||||
if (value is string)
|
||||
{
|
||||
Udi udi;
|
||||
if (Udi.TryParse((string)value, out udi))
|
||||
if (UdiParser.TryParse((string)value, out udi))
|
||||
{
|
||||
return udi;
|
||||
}
|
||||
16
src/Umbraco.Abstractions/UnknownTypeUdi.cs
Normal file
16
src/Umbraco.Abstractions/UnknownTypeUdi.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
internal class UnknownTypeUdi : Udi
|
||||
{
|
||||
private UnknownTypeUdi()
|
||||
: base("unknown", "umb://unknown/")
|
||||
{ }
|
||||
|
||||
public static readonly UnknownTypeUdi Instance = new UnknownTypeUdi();
|
||||
|
||||
public override bool IsRoot
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
GuidUdi udi = null;
|
||||
if (relatedLink.IsInternal)
|
||||
{
|
||||
var linkIsUdi = GuidUdi.TryParse(relatedLink.Link, out udi);
|
||||
var linkIsUdi = UdiParser.TryParse(relatedLink.Link, out udi);
|
||||
if (linkIsUdi == false)
|
||||
{
|
||||
// oh no.. probably an integer, yikes!
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Serialization
|
||||
{
|
||||
var jo = JToken.ReadFrom(reader);
|
||||
var val = jo.ToObject<string>();
|
||||
return val == null ? null : Udi.Parse(val, true);
|
||||
return val == null ? null : UdiParser.Parse(val, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Serialization
|
||||
{
|
||||
var jo = JToken.ReadFrom(reader);
|
||||
var val = jo.ToObject<string>();
|
||||
return val == null ? null : Udi.Parse(val);
|
||||
return val == null ? null : UdiParser.Parse(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,385 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Deploy;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entity identifier.
|
||||
/// </summary>
|
||||
/// <remarks>An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document.</remarks>
|
||||
[TypeConverter(typeof(UdiTypeConverter))]
|
||||
public abstract class Udi : IComparable<Udi>
|
||||
{
|
||||
// notes - see U4-10409
|
||||
// if this class is used during application pre-start it cannot scans the assemblies,
|
||||
// this is addressed by lazily-scanning, with the following caveats:
|
||||
// - parsing a root udi still requires a scan and therefore still breaks
|
||||
// - parsing an invalid udi ("umb://should-be-guid/<not-a-guid>") corrupts KnowUdiTypes
|
||||
|
||||
private static volatile bool _scanned;
|
||||
private static readonly object ScanLocker = new object();
|
||||
private static ConcurrentDictionary<string, UdiType> _udiTypes;
|
||||
private static readonly ConcurrentDictionary<string, Udi> RootUdis = new ConcurrentDictionary<string, Udi>();
|
||||
internal readonly Uri UriValue; // internal for UdiRange
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Udi class.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type part of the identifier.</param>
|
||||
/// <param name="stringValue">The string value of the identifier.</param>
|
||||
protected Udi(string entityType, string stringValue)
|
||||
{
|
||||
EntityType = entityType;
|
||||
UriValue = new Uri(stringValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Udi class.
|
||||
/// </summary>
|
||||
/// <param name="uriValue">The uri value of the identifier.</param>
|
||||
protected Udi(Uri uriValue)
|
||||
{
|
||||
EntityType = uriValue.Host;
|
||||
UriValue = uriValue;
|
||||
}
|
||||
|
||||
static Udi()
|
||||
{
|
||||
// initialize with known (built-in) Udi types
|
||||
// we will add scanned types later on
|
||||
_udiTypes = new ConcurrentDictionary<string, UdiType>(UdiEntityTypeHelper.GetTypes());
|
||||
}
|
||||
|
||||
// for tests, totally unsafe
|
||||
internal static void ResetUdiTypes()
|
||||
{
|
||||
_udiTypes = new ConcurrentDictionary<string, UdiType>(UdiEntityTypeHelper.GetTypes());
|
||||
_scanned = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the entity type part of the identifier.
|
||||
/// </summary>
|
||||
public string EntityType { get; private set; }
|
||||
|
||||
public int CompareTo(Udi other)
|
||||
{
|
||||
return string.Compare(UriValue.ToString(), other.UriValue.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// UriValue is created in the ctor and is never null
|
||||
// use AbsoluteUri here and not ToString else it's not encoded!
|
||||
return UriValue.AbsoluteUri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <returns>An Udi instance that contains the value that was parsed.</returns>
|
||||
public static Udi Parse(string s)
|
||||
{
|
||||
Udi udi;
|
||||
ParseInternal(s, false, false, out udi);
|
||||
return udi;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
|
||||
/// <returns>An Udi instance that contains the value that was parsed.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
|
||||
/// the entity type was not known, the method succeeds but sets <c>udi</c>to an
|
||||
/// <see cref="UnknownTypeUdi"/> value.</para>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
|
||||
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
|
||||
/// </remarks>
|
||||
public static Udi Parse(string s, bool knownTypes)
|
||||
{
|
||||
Udi udi;
|
||||
ParseInternal(s, false, knownTypes, out udi);
|
||||
return udi;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
|
||||
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
|
||||
public static bool TryParse(string s, out Udi udi)
|
||||
{
|
||||
return ParseInternal(s, true, false, out udi);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of an entity identifier into the equivalent Udi instance.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to convert.</param>
|
||||
/// <param name="knownTypes">A value indicating whether to only deal with known types.</param>
|
||||
/// <param name="udi">An Udi instance that contains the value that was parsed.</param>
|
||||
/// <returns>A boolean value indicating whether the string could be parsed.</returns>
|
||||
/// <remarks>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, and the string could not be parsed because
|
||||
/// the entity type was not known, the method returns <c>false</c> but still sets <c>udi</c>
|
||||
/// to an <see cref="UnknownTypeUdi"/> value.</para>
|
||||
/// <para>If <paramref name="knownTypes"/> is <c>true</c>, assemblies are not scanned for types,
|
||||
/// and therefore only builtin types may be known. Unless scanning already took place.</para>
|
||||
/// </remarks>
|
||||
public static bool TryParse(string s, bool knownTypes, out Udi udi)
|
||||
{
|
||||
return ParseInternal(s, true, knownTypes, out udi);
|
||||
}
|
||||
|
||||
private static bool ParseInternal(string s, bool tryParse, bool knownTypes, out Udi udi)
|
||||
{
|
||||
if (knownTypes == false)
|
||||
EnsureScanForUdiTypes();
|
||||
|
||||
udi = null;
|
||||
Uri uri;
|
||||
|
||||
if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false
|
||||
|| Uri.TryCreate(s, UriKind.Absolute, out uri) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
|
||||
}
|
||||
|
||||
var entityType = uri.Host;
|
||||
UdiType udiType;
|
||||
if (_udiTypes.TryGetValue(entityType, out udiType) == false)
|
||||
{
|
||||
if (knownTypes)
|
||||
{
|
||||
// not knowing the type is not an error
|
||||
// just return the unknown type udi
|
||||
udi = UnknownTypeUdi.Instance;
|
||||
return false;
|
||||
}
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("Unknown entity type \"{0}\".", entityType));
|
||||
}
|
||||
|
||||
var path = uri.AbsolutePath.TrimStart('/');
|
||||
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
{
|
||||
if (path == string.Empty)
|
||||
{
|
||||
udi = GetRootUdi(uri.Host);
|
||||
return true;
|
||||
}
|
||||
Guid guid;
|
||||
if (Guid.TryParse(path, out guid) == false)
|
||||
{
|
||||
if (tryParse) return false;
|
||||
throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s));
|
||||
}
|
||||
udi = new GuidUdi(uri.Host, guid);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (udiType == UdiType.StringUdi)
|
||||
{
|
||||
udi = path == string.Empty ? GetRootUdi(uri.Host) : new StringUdi(uri.Host, Uri.UnescapeDataString(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tryParse) return false;
|
||||
throw new InvalidOperationException(string.Format("Invalid udi type \"{0}\".", udiType));
|
||||
}
|
||||
|
||||
private static Udi GetRootUdi(string entityType)
|
||||
{
|
||||
EnsureScanForUdiTypes();
|
||||
|
||||
return RootUdis.GetOrAdd(entityType, x =>
|
||||
{
|
||||
UdiType udiType;
|
||||
if (_udiTypes.TryGetValue(x, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType));
|
||||
return udiType == UdiType.StringUdi
|
||||
? (Udi)new StringUdi(entityType, string.Empty)
|
||||
: new GuidUdi(entityType, Guid.Empty);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When required scan assemblies for known UDI types based on <see cref="IServiceConnector"/> instances
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is only required when needing to resolve root udis
|
||||
/// </remarks>
|
||||
private static void EnsureScanForUdiTypes()
|
||||
{
|
||||
if (_scanned) return;
|
||||
|
||||
lock (ScanLocker)
|
||||
{
|
||||
// Scan for unknown UDI types
|
||||
// there is no way we can get the "registered" service connectors, as registration
|
||||
// happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we
|
||||
// just pick every service connectors - just making sure that not two of them
|
||||
// would register the same entity type, with different udi types (would not make
|
||||
// much sense anyways).
|
||||
var connectors = Current.TypeLoader.GetTypes<IServiceConnector>();
|
||||
var result = new Dictionary<string, UdiType>();
|
||||
foreach (var connector in connectors)
|
||||
{
|
||||
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
|
||||
foreach (var attr in attrs)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (result.TryGetValue(attr.EntityType, out udiType) && udiType != attr.UdiType)
|
||||
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
|
||||
result[attr.EntityType] = attr.UdiType;
|
||||
}
|
||||
}
|
||||
|
||||
// merge these into the known list
|
||||
foreach (var item in result)
|
||||
_udiTypes.TryAdd(item.Key, item.Value);
|
||||
|
||||
_scanned = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a root Udi for an entity type.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <returns>The root Udi for the entity type.</returns>
|
||||
public static Udi Create(string entityType)
|
||||
{
|
||||
return GetRootUdi(entityType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a string Udi.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>The string Udi for the entity type and identifier.</returns>
|
||||
public static Udi Create(string entityType, string id)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (_udiTypes.TryGetValue(entityType, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
throw new ArgumentException("Value cannot be null or whitespace.", "id");
|
||||
if (udiType != UdiType.StringUdi)
|
||||
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have string udis.", entityType));
|
||||
|
||||
return new StringUdi(entityType, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Guid Udi.
|
||||
/// </summary>
|
||||
/// <param name="entityType">The entity type.</param>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <returns>The Guid Udi for the entity type and identifier.</returns>
|
||||
public static Udi Create(string entityType, Guid id)
|
||||
{
|
||||
UdiType udiType;
|
||||
if (_udiTypes.TryGetValue(entityType, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType");
|
||||
|
||||
if (udiType != UdiType.GuidUdi)
|
||||
throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType));
|
||||
if (id == default(Guid))
|
||||
throw new ArgumentException("Cannot be an empty guid.", "id");
|
||||
|
||||
return new GuidUdi(entityType, id);
|
||||
}
|
||||
|
||||
internal static Udi Create(Uri uri)
|
||||
{
|
||||
// if it's a know type go fast and use ctors
|
||||
// else fallback to parsing the string (and guess the type)
|
||||
|
||||
UdiType udiType;
|
||||
if (_udiTypes.TryGetValue(uri.Host, out udiType) == false)
|
||||
throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri");
|
||||
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
return new GuidUdi(uri);
|
||||
if (udiType == UdiType.GuidUdi)
|
||||
return new StringUdi(uri);
|
||||
|
||||
throw new ArgumentException(string.Format("Uri \"{0}\" is not a valid udi.", uri));
|
||||
}
|
||||
|
||||
public void EnsureType(params string[] validTypes)
|
||||
{
|
||||
if (validTypes.Contains(EntityType) == false)
|
||||
throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this Udi is a root Udi.
|
||||
/// </summary>
|
||||
/// <remarks>A root Udi points to the "root of all things" for a given entity type, e.g. the content tree root.</remarks>
|
||||
public abstract bool IsRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that this Udi is not a root Udi.
|
||||
/// </summary>
|
||||
/// <returns>This Udi.</returns>
|
||||
/// <exception cref="Exception">When this Udi is a Root Udi.</exception>
|
||||
public Udi EnsureNotRoot()
|
||||
{
|
||||
if (IsRoot) throw new Exception("Root Udi.");
|
||||
return this;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as Udi;
|
||||
return other != null && GetType() == other.GetType() && UriValue == other.UriValue;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return UriValue.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(Udi udi1, Udi udi2)
|
||||
{
|
||||
if (ReferenceEquals(udi1, udi2)) return true;
|
||||
if ((object)udi1 == null || (object)udi2 == null) return false;
|
||||
return udi1.Equals(udi2);
|
||||
}
|
||||
|
||||
public static bool operator !=(Udi udi1, Udi udi2)
|
||||
{
|
||||
return (udi1 == udi2) == false;
|
||||
}
|
||||
|
||||
private class UnknownTypeUdi : Udi
|
||||
{
|
||||
private UnknownTypeUdi()
|
||||
: base("unknown", "umb://unknown/")
|
||||
{ }
|
||||
|
||||
public static readonly UnknownTypeUdi Instance = new UnknownTypeUdi();
|
||||
|
||||
public override bool IsRoot
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,43 +6,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
public static class UdiEntityTypeHelper
|
||||
{
|
||||
internal static Dictionary<string, UdiType> GetTypes() =>
|
||||
new Dictionary<string, UdiType>
|
||||
{
|
||||
{ Constants.UdiEntityType.Unknown, UdiType.Unknown },
|
||||
|
||||
{ Constants.UdiEntityType.AnyGuid, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Document, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentBlueprint, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Media, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Member, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DictionaryItem, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Macro, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.Template, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentTypeContainer, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DocumentTypeBluePrints, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MediaType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MediaTypeContainer, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DataType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.DataTypeContainer, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MemberType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.MemberGroup, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.RelationType, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.FormsForm, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.FormsPreValue, UdiType.GuidUdi },
|
||||
{ Constants.UdiEntityType.FormsDataSource, UdiType.GuidUdi },
|
||||
|
||||
{ Constants.UdiEntityType.AnyString, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.Language, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.MacroScript, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.MediaFile, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.TemplateFile, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.Script, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.PartialView, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.PartialViewMacro, UdiType.StringUdi },
|
||||
{ Constants.UdiEntityType.Stylesheet, UdiType.StringUdi }
|
||||
};
|
||||
|
||||
|
||||
public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
|
||||
82
src/Umbraco.Core/UdiParserServiceConnectors.cs
Normal file
82
src/Umbraco.Core/UdiParserServiceConnectors.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Deploy;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class UdiParserServiceConnectors
|
||||
{
|
||||
// notes - see U4-10409
|
||||
// if this class is used during application pre-start it cannot scans the assemblies,
|
||||
// this is addressed by lazily-scanning, with the following caveats:
|
||||
// - parsing a root udi still requires a scan and therefore still breaks
|
||||
// - parsing an invalid udi ("umb://should-be-guid/<not-a-guid>") corrupts KnowUdiTypes
|
||||
|
||||
private static volatile bool _scanned;
|
||||
private static readonly object ScanLocker = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Scan for deploy <see cref="IServiceConnector"/> in assemblies for known UDI types.
|
||||
/// </summary>
|
||||
/// <param name="typeLoader"></param>
|
||||
public static void ScanDeployServiceConnectorsForUdiTypes(TypeLoader typeLoader)
|
||||
{
|
||||
if (typeLoader is null)
|
||||
throw new ArgumentNullException(nameof(typeLoader));
|
||||
|
||||
if (_scanned) return;
|
||||
|
||||
lock (ScanLocker)
|
||||
{
|
||||
// Scan for unknown UDI types
|
||||
// there is no way we can get the "registered" service connectors, as registration
|
||||
// happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we
|
||||
// just pick every service connectors - just making sure that not two of them
|
||||
// would register the same entity type, with different udi types (would not make
|
||||
// much sense anyways)
|
||||
var connectors = typeLoader.GetTypes<IServiceConnector>();
|
||||
var result = new Dictionary<string, UdiType>();
|
||||
foreach (var connector in connectors)
|
||||
{
|
||||
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
|
||||
foreach (var attr in attrs)
|
||||
{
|
||||
if (result.TryGetValue(attr.EntityType, out var udiType) && udiType != attr.UdiType)
|
||||
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
|
||||
result[attr.EntityType] = attr.UdiType;
|
||||
}
|
||||
}
|
||||
|
||||
// merge these into the known list
|
||||
foreach (var item in result)
|
||||
UdiParser.RegisterUdiType(item.Key, item.Value);
|
||||
|
||||
_scanned = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a single <see cref="IServiceConnector"/> to add it's UDI type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public static void RegisterServiceConnector<T>()
|
||||
where T: IServiceConnector
|
||||
{
|
||||
var result = new Dictionary<string, UdiType>();
|
||||
var connector = typeof(T);
|
||||
var attrs = connector.GetCustomAttributes<UdiDefinitionAttribute>(false);
|
||||
foreach (var attr in attrs)
|
||||
{
|
||||
if (result.TryGetValue(attr.EntityType, out var udiType) && udiType != attr.UdiType)
|
||||
throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType));
|
||||
result[attr.EntityType] = attr.UdiType;
|
||||
}
|
||||
|
||||
// merge these into the known list
|
||||
foreach (var item in result)
|
||||
UdiParser.RegisterUdiType(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -446,7 +446,6 @@
|
||||
<Compile Include="Events\UninstallPackageEventArgs.cs" />
|
||||
<Compile Include="Composing\LightInject\LightInjectException.cs" />
|
||||
<Compile Include="FileResources\Files.Designer.cs" />
|
||||
<Compile Include="GuidUdi.cs" />
|
||||
<Compile Include="HttpContextExtensions.cs" />
|
||||
<Compile Include="IO\FileSecurityException.cs" />
|
||||
<Compile Include="IO\FileSystemExtensions.cs" />
|
||||
@@ -565,7 +564,6 @@
|
||||
<Compile Include="Models\UmbracoObjectTypes.cs" />
|
||||
<Compile Include="Models\UserExtensions.cs" />
|
||||
<Compile Include="Models\Validation\RequiredForPersistenceAttribute.cs" />
|
||||
<Compile Include="NamedUdiRange.cs" />
|
||||
<Compile Include="NameValueCollectionExtensions.cs" />
|
||||
<Compile Include="ObjectJsonExtensions.cs" />
|
||||
<Compile Include="Packaging\ConflictingPackageData.cs" />
|
||||
@@ -993,17 +991,13 @@
|
||||
<Compile Include="Compose\RelateOnCopyComponent.cs" />
|
||||
<Compile Include="Compose\RelateOnTrashComponent.cs" />
|
||||
<Compile Include="Strings\UrlSegmentProviderCollectionBuilder.cs" />
|
||||
<Compile Include="StringUdi.cs" />
|
||||
<Compile Include="Sync\ApplicationUrlHelper.cs" />
|
||||
<Compile Include="Sync\DatabaseServerMessenger.cs" />
|
||||
<Compile Include="Sync\RefreshInstruction.cs" />
|
||||
<Compile Include="Sync\ServerMessengerBase.cs" />
|
||||
<Compile Include="Udi.cs" />
|
||||
<Compile Include="UdiDefinitionAttribute.cs" />
|
||||
<Compile Include="UdiEntityTypeHelper.cs" />
|
||||
<Compile Include="UdiGetterExtensions.cs" />
|
||||
<Compile Include="UdiRange.cs" />
|
||||
<Compile Include="UdiTypeConverter.cs" />
|
||||
<Compile Include="UdiParserServiceConnectors.cs" />
|
||||
<Compile Include="UriExtensions.cs" />
|
||||
<Compile Include="PackageActions\IPackageAction.cs" />
|
||||
<Compile Include="PackageActions\PackageActionCollection.cs" />
|
||||
|
||||
@@ -24,21 +24,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
// FIXME: bad in a unit test - but Udi has a static ctor that wants it?!
|
||||
var container = new Mock<IFactory>();
|
||||
var ioHelper = IOHelper.Default;
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>());
|
||||
container.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns(
|
||||
new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
Current.Factory = container.Object;
|
||||
|
||||
Udi.ResetUdiTypes();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Current.Reset();
|
||||
UdiParser.ResetUdiTypes();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -53,7 +39,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
[Test]
|
||||
public void StringUdiParseTest()
|
||||
{
|
||||
var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/test-id");
|
||||
var udi = UdiParser.Parse("umb://" + Constants.UdiEntityType.AnyString + "/test-id");
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
|
||||
Assert.IsInstanceOf<StringUdi>(udi);
|
||||
var stringEntityId = udi as StringUdi;
|
||||
@@ -61,7 +47,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
Assert.AreEqual("test-id", stringEntityId.Id);
|
||||
Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString());
|
||||
|
||||
udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/DA845952BE474EE9BD6F6194272AC750");
|
||||
udi = UdiParser.Parse("umb://" + Constants.UdiEntityType.AnyString + "/DA845952BE474EE9BD6F6194272AC750");
|
||||
Assert.IsInstanceOf<StringUdi>(udi);
|
||||
}
|
||||
|
||||
@@ -78,7 +64,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
Assert.AreEqual("%2Fthis%20is%20a%20test", Uri.EscapeDataString("/this is a test"));
|
||||
Assert.AreEqual("/this%20is%20a%20test", Uri.EscapeUriString("/this is a test"));
|
||||
|
||||
var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test");
|
||||
var udi = UdiParser.Parse("umb://" + Constants.UdiEntityType.AnyString + "/this%20is%20a%20test");
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType);
|
||||
Assert.IsInstanceOf<StringUdi>(udi);
|
||||
var stringEntityId = udi as StringUdi;
|
||||
@@ -112,7 +98,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
// with the proper fix in StringUdi this should work:
|
||||
var udi1 = new StringUdi("partial-view-macro", "path/to/View[1].cshtml");
|
||||
Assert.AreEqual("umb://partial-view-macro/path/to/View%5B1%5D.cshtml", udi1.ToString());
|
||||
var udi2 = Udi.Parse("umb://partial-view-macro/path/to/View%5B1%5D.cshtml");
|
||||
var udi2 = UdiParser.Parse("umb://partial-view-macro/path/to/View%5B1%5D.cshtml");
|
||||
Assert.AreEqual("path/to/View[1].cshtml", ((StringUdi) udi2).Id);
|
||||
}
|
||||
|
||||
@@ -131,7 +117,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
{
|
||||
var guid = Guid.NewGuid();
|
||||
var s = "umb://" + Constants.UdiEntityType.AnyGuid + "/" + guid.ToString("N");
|
||||
var udi = Udi.Parse(s);
|
||||
var udi = UdiParser.Parse(s);
|
||||
Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType);
|
||||
Assert.IsInstanceOf<GuidUdi>(udi);
|
||||
var gudi = udi as GuidUdi;
|
||||
@@ -198,15 +184,15 @@ namespace Umbraco.Tests.CoreThings
|
||||
Assert.IsTrue(guidUdi.IsRoot);
|
||||
Assert.AreEqual("umb://any-guid/00000000000000000000000000000000", guidUdi.ToString());
|
||||
|
||||
var udi = Udi.Parse("umb://any-string/");
|
||||
var udi = UdiParser.Parse("umb://any-string/");
|
||||
Assert.IsTrue(udi.IsRoot);
|
||||
Assert.IsInstanceOf<StringUdi>(udi);
|
||||
|
||||
udi = Udi.Parse("umb://any-guid/00000000000000000000000000000000");
|
||||
udi = UdiParser.Parse("umb://any-guid/00000000000000000000000000000000");
|
||||
Assert.IsTrue(udi.IsRoot);
|
||||
Assert.IsInstanceOf<GuidUdi>(udi);
|
||||
|
||||
udi = Udi.Parse("umb://any-guid/");
|
||||
udi = UdiParser.Parse("umb://any-guid/");
|
||||
Assert.IsTrue(udi.IsRoot);
|
||||
Assert.IsInstanceOf<GuidUdi>(udi);
|
||||
}
|
||||
@@ -217,13 +203,13 @@ namespace Umbraco.Tests.CoreThings
|
||||
// can parse open string udi
|
||||
var stringUdiString = "umb://" + Constants.UdiEntityType.AnyString;
|
||||
Udi stringUdi;
|
||||
Assert.IsTrue(Udi.TryParse(stringUdiString, out stringUdi));
|
||||
Assert.IsTrue(UdiParser.TryParse(stringUdiString, out stringUdi));
|
||||
Assert.AreEqual(string.Empty, ((StringUdi)stringUdi).Id);
|
||||
|
||||
// can parse open guid udi
|
||||
var guidUdiString = "umb://" + Constants.UdiEntityType.AnyGuid;
|
||||
Udi guidUdi;
|
||||
Assert.IsTrue(Udi.TryParse(guidUdiString, out guidUdi));
|
||||
Assert.IsTrue(UdiParser.TryParse(guidUdiString, out guidUdi));
|
||||
Assert.AreEqual(Guid.Empty, ((GuidUdi)guidUdi).Guid);
|
||||
|
||||
// can create a range
|
||||
@@ -264,7 +250,7 @@ namespace Umbraco.Tests.CoreThings
|
||||
[Test]
|
||||
public void ValidateUdiEntityType()
|
||||
{
|
||||
var types = UdiEntityTypeHelper.GetTypes();
|
||||
var types = UdiParser.GetKnownUdiTypes();
|
||||
|
||||
foreach (var fi in typeof(Constants.UdiEntityType).GetFields(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
@@ -294,33 +280,34 @@ namespace Umbraco.Tests.CoreThings
|
||||
|
||||
// cannot parse an unknown type, udi is null
|
||||
// this will scan
|
||||
Assert.IsFalse(Udi.TryParse("umb://whatever/1234", out udi));
|
||||
Assert.IsFalse(UdiParser.TryParse("umb://whatever/1234", out udi));
|
||||
Assert.IsNull(udi);
|
||||
|
||||
Udi.ResetUdiTypes();
|
||||
|
||||
UdiParser.ResetUdiTypes();
|
||||
|
||||
// unless we want to know
|
||||
Assert.IsFalse(Udi.TryParse("umb://whatever/1234", true, out udi));
|
||||
Assert.IsFalse(UdiParser.TryParse("umb://whatever/1234", true, out udi));
|
||||
Assert.AreEqual(Constants.UdiEntityType.Unknown, udi.EntityType);
|
||||
Assert.AreEqual("Umbraco.Core.Udi+UnknownTypeUdi", udi.GetType().FullName);
|
||||
|
||||
Udi.ResetUdiTypes();
|
||||
Assert.AreEqual("Umbraco.Core.UnknownTypeUdi", udi.GetType().FullName);
|
||||
|
||||
UdiParser.ResetUdiTypes();
|
||||
|
||||
// not known
|
||||
Assert.IsFalse(Udi.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
|
||||
Assert.IsFalse(UdiParser.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
|
||||
Assert.AreEqual(Constants.UdiEntityType.Unknown, udi.EntityType);
|
||||
Assert.AreEqual("Umbraco.Core.Udi+UnknownTypeUdi", udi.GetType().FullName);
|
||||
Assert.AreEqual("Umbraco.Core.UnknownTypeUdi", udi.GetType().FullName);
|
||||
|
||||
// scanned
|
||||
Assert.IsTrue(Udi.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", out udi));
|
||||
// scanned
|
||||
UdiParserServiceConnectors.RegisterServiceConnector<FooConnector>(); // this is the equivalent of scanning but we'll just manually register this one
|
||||
Assert.IsTrue(UdiParser.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", out udi));
|
||||
Assert.IsInstanceOf<GuidUdi>(udi);
|
||||
|
||||
// known
|
||||
Assert.IsTrue(Udi.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
|
||||
Assert.IsTrue(UdiParser.TryParse("umb://foo/A87F65C8D6B94E868F6949BA92C93045", true, out udi));
|
||||
Assert.IsInstanceOf<GuidUdi>(udi);
|
||||
|
||||
// can get method for Deploy compatibility
|
||||
var method = typeof(Udi).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string), typeof(bool) }, null);
|
||||
var method = typeof(UdiParser).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string), typeof(bool) }, null);
|
||||
Assert.IsNotNull(method);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -17,10 +13,7 @@ using Umbraco.Tests.Testing.Objects.Accessors;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Templates;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Tests.Web
|
||||
{
|
||||
@@ -30,37 +23,9 @@ namespace Umbraco.Tests.Web
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
Current.Reset();
|
||||
|
||||
// FIXME: now UrlProvider depends on EntityService for GetUrl(guid) - this is bad
|
||||
// should not depend on more than IdkMap maybe - fix this!
|
||||
var entityService = new Mock<IEntityService>();
|
||||
entityService.Setup(x => x.GetId(It.IsAny<Guid>(), It.IsAny<UmbracoObjectTypes>())).Returns(Attempt<int>.Fail());
|
||||
var serviceContext = ServiceContext.CreatePartial(entityService: entityService.Object);
|
||||
|
||||
// FIXME: bad in a unit test - but Udi has a static ctor that wants it?!
|
||||
var factory = new Mock<IFactory>();
|
||||
var typeFinder = new TypeFinder(Mock.Of<ILogger>());
|
||||
var ioHelper = IOHelper.Default;
|
||||
factory.Setup(x => x.GetInstance(typeof(TypeLoader))).Returns(
|
||||
new TypeLoader(ioHelper, typeFinder, NoAppCache.Instance, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>())));
|
||||
factory.Setup(x => x.GetInstance(typeof (ServiceContext))).Returns(serviceContext);
|
||||
|
||||
var settings = SettingsForTests.GetDefaultUmbracoSettings();
|
||||
factory.Setup(x => x.GetInstance(typeof(IUmbracoSettingsSection))).Returns(settings);
|
||||
|
||||
Current.Factory = factory.Object;
|
||||
|
||||
Umbraco.Web.Composing.Current.UmbracoContextAccessor = new TestUmbracoContextAccessor();
|
||||
|
||||
Udi.ResetUdiTypes();
|
||||
UdiParser.ResetUdiTypes();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Current.Reset();
|
||||
}
|
||||
|
||||
[TestCase("", "")]
|
||||
[TestCase("hello href=\"{localLink:1234}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
@@ -71,17 +36,7 @@ namespace Umbraco.Tests.Web
|
||||
[TestCase("hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")]
|
||||
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"#\" world ")]
|
||||
public void ParseLocalLinks(string input, string result)
|
||||
{
|
||||
var serviceCtxMock = new TestObjects(null).GetServiceContextMock();
|
||||
|
||||
//setup a mock entity service from the service context to return an integer for a GUID
|
||||
var entityService = Mock.Get(serviceCtxMock.EntityService);
|
||||
//entityService.Setup(x => x.GetId(It.IsAny<Guid>(), It.IsAny<UmbracoObjectTypes>()))
|
||||
// .Returns((Guid id, UmbracoObjectTypes objType) =>
|
||||
// {
|
||||
// return Attempt.Succeed(1234);
|
||||
// });
|
||||
|
||||
{
|
||||
//setup a mock url provider which we'll use for testing
|
||||
var testUrlProvider = new Mock<IUrlProvider>();
|
||||
testUrlProvider
|
||||
@@ -106,8 +61,9 @@ namespace Umbraco.Tests.Web
|
||||
var mediaCache = Mock.Of<IPublishedMediaCache>();
|
||||
Mock.Get(mediaCache).Setup(x => x.GetById(It.IsAny<Guid>())).Returns(media);
|
||||
|
||||
var umbracoContextAccessor = new TestUmbracoContextAccessor();
|
||||
var umbracoContextFactory = new UmbracoContextFactory(
|
||||
Umbraco.Web.Composing.Current.UmbracoContextAccessor,
|
||||
umbracoContextAccessor,
|
||||
snapshotService,
|
||||
new TestVariationContextAccessor(),
|
||||
new TestDefaultCultureAccessor(),
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace Umbraco.Tests.Web
|
||||
public static void Converting_Boxed_Udi_To_A_Udi_Returns_Original_Udi_Value()
|
||||
{
|
||||
// Arrange
|
||||
Udi.ResetUdiTypes();
|
||||
UdiParser.ResetUdiTypes();
|
||||
Udi sample = new GuidUdi(Constants.UdiEntityType.AnyGuid, Guid.NewGuid());
|
||||
|
||||
// Act
|
||||
@@ -198,7 +198,7 @@ namespace Umbraco.Tests.Web
|
||||
{
|
||||
// Arrange
|
||||
SetUpDependencyContainer();
|
||||
Udi.ResetUdiTypes();
|
||||
UdiParser.ResetUdiTypes();
|
||||
Udi sample = new GuidUdi(Constants.UdiEntityType.AnyGuid, Guid.NewGuid());
|
||||
|
||||
// Act
|
||||
@@ -220,7 +220,7 @@ namespace Umbraco.Tests.Web
|
||||
{
|
||||
// Arrange
|
||||
SetUpDependencyContainer();
|
||||
Udi.ResetUdiTypes();
|
||||
UdiParser.ResetUdiTypes();
|
||||
const string sample = "Hello";
|
||||
|
||||
// Act
|
||||
@@ -241,7 +241,7 @@ namespace Umbraco.Tests.Web
|
||||
public static void Converting_Unsupported_Object_To_A_Udi_Returns_False()
|
||||
{
|
||||
// Arrange
|
||||
Udi.ResetUdiTypes();
|
||||
UdiParser.ResetUdiTypes();
|
||||
|
||||
var clearlyWillNotConvertToGuid = new StringBuilder(0);
|
||||
|
||||
|
||||
@@ -509,7 +509,7 @@ namespace Umbraco.Web.Editors
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
if (Udi.TryParse(id, out _))
|
||||
if (UdiParser.TryParse(id, out _))
|
||||
{
|
||||
//Not supported currently
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
@@ -793,10 +793,9 @@ namespace Umbraco.Web.Editors
|
||||
private int GetParentIdAsInt(string parentId, bool validatePermissions)
|
||||
{
|
||||
int intParentId;
|
||||
GuidUdi parentUdi;
|
||||
|
||||
// test for udi
|
||||
if (GuidUdi.TryParse(parentId, out parentUdi))
|
||||
if (UdiParser.TryParse(parentId, out GuidUdi parentUdi))
|
||||
{
|
||||
parentId = parentUdi.Guid.ToString();
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Umbraco.Web.Editors
|
||||
public RedirectUrlSearchResult RedirectUrlsForContentItem(string contentUdi)
|
||||
{
|
||||
var redirectsResult = new RedirectUrlSearchResult();
|
||||
if (GuidUdi.TryParse(contentUdi, out var guidIdi))
|
||||
if (UdiParser.TryParse(contentUdi, out GuidUdi guidIdi))
|
||||
{
|
||||
var redirectUrlService = Services.RedirectUrlService;
|
||||
var redirects = redirectUrlService.GetContentRedirectUrls(guidIdi.Guid);
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
|
||||
var nodeIds = source.ToString()
|
||||
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(Udi.Parse)
|
||||
.Select(UdiParser.Parse)
|
||||
.ToArray();
|
||||
return nodeIds;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
var nodeIds = source.ToString()
|
||||
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(Udi.Parse)
|
||||
.Select(UdiParser.Parse)
|
||||
.ToArray();
|
||||
return nodeIds;
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ namespace Umbraco.Web.Search
|
||||
if (sb == null) throw new ArgumentNullException(nameof(sb));
|
||||
if (entityService == null) throw new ArgumentNullException(nameof(entityService));
|
||||
|
||||
Udi.TryParse(searchFrom, true, out var udi);
|
||||
UdiParser.TryParse(searchFrom, true, out var udi);
|
||||
searchFrom = udi == null ? searchFrom : entityService.GetId(udi).Result.ToString();
|
||||
|
||||
var entityPath = int.TryParse(searchFrom, out var searchFromId) && searchFromId > 0
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Umbraco.Web.Templates
|
||||
var id = tag.Groups[1].Value; //.Remove(tag.Groups[1].Value.Length - 1, 1);
|
||||
|
||||
//The id could be an int or a UDI
|
||||
if (Udi.TryParse(id, out var udi))
|
||||
if (UdiParser.TryParse(id, out var udi))
|
||||
{
|
||||
var guidUdi = udi as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
@@ -166,7 +166,7 @@ namespace Umbraco.Web.Templates
|
||||
// - 4 = the data-udi attribute value
|
||||
// - 5 = anything after group 4 until the image tag is closed
|
||||
var udi = match.Groups[4].Value;
|
||||
if(udi.IsNullOrWhiteSpace() || GuidUdi.TryParse(udi, out var guidUdi) == false)
|
||||
if(udi.IsNullOrWhiteSpace() || UdiParser.TryParse(udi, out GuidUdi guidUdi) == false)
|
||||
{
|
||||
return match.Value;
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
return new Tuple<Guid?, int?>(null, idInt);
|
||||
}
|
||||
if (Udi.TryParse(id, out idUdi))
|
||||
if (UdiParser.TryParse(id, out idUdi))
|
||||
{
|
||||
var guidUdi = idUdi as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
@@ -523,7 +523,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
entity = Services.EntityService.Get(idInt, UmbracoObjectType);
|
||||
}
|
||||
else if (Udi.TryParse(s, out var idUdi))
|
||||
else if (UdiParser.TryParse(s, out var idUdi))
|
||||
{
|
||||
var guidUdi = idUdi as GuidUdi;
|
||||
entity = guidUdi != null ? Services.EntityService.Get(guidUdi.Guid, UmbracoObjectType) : null;
|
||||
|
||||
@@ -621,7 +621,7 @@ namespace Umbraco.Web
|
||||
switch (id)
|
||||
{
|
||||
case string s:
|
||||
return Udi.TryParse(s, out guidId);
|
||||
return UdiParser.TryParse(s, out guidId);
|
||||
|
||||
case Udi u:
|
||||
guidId = u;
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
nodeId = parsedId;
|
||||
}
|
||||
else if (Udi.TryParse(argument, true, out Udi udi))
|
||||
else if (UdiParser.TryParse(argument, true, out Udi udi))
|
||||
{
|
||||
// TODO: inject? we can't because this is an attribute but we could provide ctors and empty ctors that pass in the required services
|
||||
nodeId = Current.Services.EntityService.GetId(udi).Result;
|
||||
|
||||
Reference in New Issue
Block a user