diff --git a/src/Umbraco.Core/Models/Member.cs b/src/Umbraco.Core/Models/Member.cs
index 4af0c79c13..e35efb726b 100644
--- a/src/Umbraco.Core/Models/Member.cs
+++ b/src/Umbraco.Core/Models/Member.cs
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models
public class Member : ContentBase, IMember
{
private readonly IMemberType _contentType;
- private string _contentTypeAlias;
+ private readonly string _contentTypeAlias;
private string _username;
private string _email;
private string _password;
@@ -30,6 +30,7 @@ namespace Umbraco.Core.Models
public Member(string name, IMemberType contentType)
: base(name, -1, contentType, new PropertyCollection())
{
+ _contentTypeAlias = contentType.Alias;
_contentType = contentType;
IsApproved = true;
}
@@ -40,6 +41,7 @@ namespace Umbraco.Core.Models
{
Mandate.ParameterNotNull(contentType, "contentType");
+ _contentTypeAlias = contentType.Alias;
_contentType = contentType;
_email = email;
_username = username;
@@ -52,6 +54,7 @@ namespace Umbraco.Core.Models
{
Mandate.ParameterNotNull(contentType, "contentType");
+ _contentTypeAlias = contentType.Alias;
_contentType = contentType;
_email = email;
_username = username;
@@ -424,14 +427,6 @@ namespace Umbraco.Core.Models
public virtual string ContentTypeAlias
{
get { return _contentTypeAlias; }
- internal set
- {
- SetPropertyValueAndDetectChanges(o =>
- {
- _contentTypeAlias = value;
- return _contentTypeAlias;
- }, _contentTypeAlias, DefaultContentTypeAliasSelector);
- }
}
///
diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs
index eb53215896..453e8b0862 100644
--- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs
+++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs
@@ -141,9 +141,21 @@ namespace Umbraco.Core.Models.PublishedContent
if (GetPublishedContentTypeCallback != null)
return GetPublishedContentTypeCallback(alias);
- var contentType = itemType == PublishedItemType.Content
- ? (IContentTypeComposition)ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias)
- : (IContentTypeComposition)ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);
+ IContentTypeComposition contentType;
+ switch (itemType)
+ {
+ case PublishedItemType.Content:
+ contentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(alias);
+ break;
+ case PublishedItemType.Media:
+ contentType = ApplicationContext.Current.Services.ContentTypeService.GetMediaType(alias);
+ break;
+ case PublishedItemType.Member:
+ contentType = ApplicationContext.Current.Services.MemberTypeService.Get(alias);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("itemType");
+ }
if (contentType == null)
throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
diff --git a/src/Umbraco.Core/Models/PublishedItemType.cs b/src/Umbraco.Core/Models/PublishedItemType.cs
index a98a3c2a75..681fec8854 100644
--- a/src/Umbraco.Core/Models/PublishedItemType.cs
+++ b/src/Umbraco.Core/Models/PublishedItemType.cs
@@ -13,6 +13,11 @@ namespace Umbraco.Core.Models
///
/// A media.
///
- Media
+ Media,
+
+ ///
+ /// A member.
+ ///
+ Member
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
index dd7d8d9277..0cef37ce8b 100644
--- a/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
+++ b/src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
@@ -33,7 +33,6 @@ namespace Umbraco.Core.Persistence.Factories
Path = dto.Path,
SortOrder = dto.SortOrder,
Version = dto.VersionId,
- ContentTypeAlias = dto.ContentTypeAlias,
Properties = new PropertyCollection(properties)
};
diff --git a/src/Umbraco.Core/TypeExtensions.cs b/src/Umbraco.Core/TypeExtensions.cs
index 281901504f..d61ad60144 100644
--- a/src/Umbraco.Core/TypeExtensions.cs
+++ b/src/Umbraco.Core/TypeExtensions.cs
@@ -7,11 +7,59 @@ using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
+using Umbraco.Core.Strings;
namespace Umbraco.Core
{
public static class TypeExtensions
{
+ ///
+ /// Tries to return a value based on a property name for an object but ignores case sensitivity
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Currenty this will only work for ProperCase and camelCase properties, see the TODO below to enable complete case insensitivity
+ ///
+ internal static Attempt
[ReadOnly(true)]
- [Obsolete("This is not used and will be removed from the codebase in future versions")]
public string MemberTypeAlias { get; set; }
[ReadOnly(true)]
@@ -88,7 +96,7 @@ namespace Umbraco.Web.Models
///
/// Adding items to this list on the front-end will not add properties to the member in the database.
///
- public List MemberProperties { get; set; }
-
+ public List MemberProperties { get; set; }
+
}
}
diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs
index 3db343c8db..2ca1978c29 100644
--- a/src/Umbraco.Web/Models/PublishedContentBase.cs
+++ b/src/Umbraco.Web/Models/PublishedContentBase.cs
@@ -50,7 +50,7 @@ namespace Umbraco.Web.Models
_url = prop.Value.ToString();
break;
default:
- throw new ArgumentOutOfRangeException();
+ throw new NotSupportedException();
}
return _url;
diff --git a/src/Umbraco.Web/Models/UmbracoProperty.cs b/src/Umbraco.Web/Models/UmbracoProperty.cs
index ad907df1a0..712e6c33db 100644
--- a/src/Umbraco.Web/Models/UmbracoProperty.cs
+++ b/src/Umbraco.Web/Models/UmbracoProperty.cs
@@ -1,4 +1,8 @@
-namespace Umbraco.Web.Models
+using System.Xml;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+
+namespace Umbraco.Web.Models
{
///
/// A simple representation of an Umbraco property
@@ -6,7 +10,8 @@
public class UmbracoProperty
{
public string Alias { get; set; }
- public string Value { get; set; }
+ public object Value { get; set; }
public string Name { get; set; }
+
}
}
diff --git a/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs b/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs
new file mode 100644
index 0000000000..6de2d37812
--- /dev/null
+++ b/src/Umbraco.Web/PublishedCache/MemberPublishedContent.cs
@@ -0,0 +1,219 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Web.Security;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.PublishedContent;
+using Umbraco.Web.Models;
+
+namespace Umbraco.Web.PublishedCache
+{
+ ///
+ /// Exposes a member object as IPublishedContent
+ ///
+ internal class MemberPublishedContent : PublishedContentBase
+ {
+
+ private readonly IMember _member;
+ private readonly MembershipUser _membershipUser;
+ private readonly List _properties;
+ private readonly PublishedContentType _publishedMemberType;
+
+ public MemberPublishedContent(IMember member, MembershipUser membershipUser)
+ {
+ if (member == null) throw new ArgumentNullException("member");
+ if (membershipUser == null) throw new ArgumentNullException("membershipUser");
+
+ _member = member;
+ _membershipUser = membershipUser;
+ _properties = new List();
+ _publishedMemberType = PublishedContentType.Get(PublishedItemType.Member, _member.ContentTypeAlias);
+ if (_publishedMemberType == null)
+ {
+ throw new InvalidOperationException("Could not get member type with alias " + _member.ContentTypeAlias);
+ }
+ foreach (var propType in _publishedMemberType.PropertyTypes)
+ {
+ var val = _member.Properties.Any(x => x.Alias == propType.PropertyTypeAlias) == false
+ ? string.Empty
+ : _member.Properties[propType.PropertyTypeAlias].Value;
+ _properties.Add(new RawValueProperty(propType, val));
+ }
+ }
+
+ #region Membership provider member properties
+ public string Email
+ {
+ get { return _membershipUser.Email; }
+ }
+ public string UserName
+ {
+ get { return _membershipUser.UserName; }
+ }
+ public string PasswordQuestion
+ {
+ get { return _membershipUser.PasswordQuestion; }
+ }
+ public string Comment
+ {
+ get { return _membershipUser.Comment; }
+ }
+ public bool IsApproved
+ {
+ get { return _membershipUser.IsApproved; }
+ }
+ public bool IsLockedOut
+ {
+ get { return _membershipUser.IsLockedOut; }
+ }
+ public DateTime LastLockoutDate
+ {
+ get { return _membershipUser.LastLockoutDate; }
+ }
+ public DateTime CreationDate
+ {
+ get { return _membershipUser.CreationDate; }
+ }
+ public DateTime LastLoginDate
+ {
+ get { return _membershipUser.LastLoginDate; }
+ }
+ public DateTime LastActivityDate
+ {
+ get { return _membershipUser.LastActivityDate; }
+ }
+ public DateTime LastPasswordChangedDate
+ {
+ get { return _membershipUser.LastPasswordChangedDate; }
+ }
+ #endregion
+
+ #region IPublishedContent
+ public override PublishedItemType ItemType
+ {
+ get { return PublishedItemType.Member; }
+ }
+
+ public override bool IsDraft
+ {
+ get { return false; }
+ }
+
+ public override IPublishedContent Parent
+ {
+ get { return null; }
+ }
+
+ public override IEnumerable Children
+ {
+ get { return Enumerable.Empty(); }
+ }
+
+ public override ICollection Properties
+ {
+ get { return _properties; }
+ }
+
+ public override IPublishedProperty GetProperty(string alias, bool recurse)
+ {
+ if (recurse)
+ {
+ throw new NotSupportedException();
+ }
+ return GetProperty(alias);
+ }
+
+ public override IPublishedProperty GetProperty(string alias)
+ {
+ return _properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias));
+ }
+
+ public override PublishedContentType ContentType
+ {
+ get { return _publishedMemberType; }
+ }
+
+ public override int Id
+ {
+ get { return _member.Id; }
+ }
+
+ public override int TemplateId
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override int SortOrder
+ {
+ get { return 0; }
+ }
+
+ public override string Name
+ {
+ get { return _member.Name; }
+ }
+
+ public override string UrlName
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override string DocumentTypeAlias
+ {
+ get { return _member.ContentTypeAlias; }
+ }
+
+ public override int DocumentTypeId
+ {
+ get { return _member.ContentType.Id; }
+ }
+
+ public override string WriterName
+ {
+ get { return _member.GetCreatorProfile().Name; }
+ }
+
+ public override string CreatorName
+ {
+ get { return _member.GetCreatorProfile().Name; }
+ }
+
+ public override int WriterId
+ {
+ get { return _member.CreatorId; }
+ }
+
+ public override int CreatorId
+ {
+ get { return _member.CreatorId; }
+ }
+
+ public override string Path
+ {
+ get { return _member.Path; }
+ }
+
+ public override DateTime CreateDate
+ {
+ get { return _member.CreateDate; }
+ }
+
+ public override DateTime UpdateDate
+ {
+ get { return _member.UpdateDate; }
+ }
+
+ public override Guid Version
+ {
+ get { return _member.Version; }
+ }
+
+ public override int Level
+ {
+ get { return _member.Level; }
+ }
+ #endregion
+ }
+}
diff --git a/src/Umbraco.Web/PublishedCache/RawValueProperty.cs b/src/Umbraco.Web/PublishedCache/RawValueProperty.cs
new file mode 100644
index 0000000000..5fa95f127b
--- /dev/null
+++ b/src/Umbraco.Web/PublishedCache/RawValueProperty.cs
@@ -0,0 +1,46 @@
+using System;
+using Umbraco.Core.Models.PublishedContent;
+
+namespace Umbraco.Web.PublishedCache
+{
+ ///
+ /// A published property base that uses a raw object value
+ ///
+ internal class RawValueProperty : PublishedPropertyBase
+ {
+ private readonly object _dbVal; //the value in the db
+ private readonly Lazy _sourceValue;
+ private readonly Lazy _objectValue;
+ private readonly Lazy _xpathValue;
+
+ ///
+ /// Gets the raw value of the property.
+ ///
+ public override object DataValue { get { return _dbVal; } }
+
+ public override bool HasValue
+ {
+ get { return _dbVal != null && _dbVal.ToString().Trim().Length > 0; }
+ }
+
+ public override object Value { get { return _objectValue.Value; } }
+ public override object XPathValue { get { return _xpathValue.Value; } }
+
+ public RawValueProperty(PublishedPropertyType propertyType, object propertyData)
+ : this(propertyType)
+ {
+ if (propertyData == null)
+ throw new ArgumentNullException("propertyData");
+ _dbVal = propertyData;
+ }
+
+ public RawValueProperty(PublishedPropertyType propertyType)
+ : base(propertyType)
+ {
+ _dbVal = null;
+ _sourceValue = new Lazy(() => PropertyType.ConvertDataToSource(_dbVal, false));
+ _objectValue = new Lazy(() => PropertyType.ConvertSourceToObject(_sourceValue.Value, false));
+ _xpathValue = new Lazy(() => PropertyType.ConvertSourceToXPath(_sourceValue.Value, false));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs
index 78f7ab09a8..c8866e624c 100644
--- a/src/Umbraco.Web/Security/MembershipHelper.cs
+++ b/src/Umbraco.Web/Security/MembershipHelper.cs
@@ -10,6 +10,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Security;
using Umbraco.Web.Models;
+using Umbraco.Web.PublishedCache;
namespace Umbraco.Web.Security
{
@@ -192,11 +193,41 @@ namespace Umbraco.Web.Security
return true;
}
+ #region Querying for front-end
+
+ public IPublishedContent GetByProviderKey(object key)
+ {
+ var result = _applicationContext.Services.MemberService.GetByProviderKey(key);
+ return result == null ? null : new MemberPublishedContent(result, Membership.GetUser(result.Username));
+ }
+
+ public IPublishedContent GetById(int memberId)
+ {
+ var result = _applicationContext.Services.MemberService.GetById(memberId);
+ return result == null ? null : new MemberPublishedContent(result, Membership.GetUser(result.Username));
+ }
+
+ public IPublishedContent GetByUsername(string username)
+ {
+ var result = _applicationContext.Services.MemberService.GetByUsername(username);
+ return result == null ? null : new MemberPublishedContent(result, Membership.GetUser(result.Username));
+ }
+
+ public IPublishedContent GetByEmail(string email)
+ {
+ var result = _applicationContext.Services.MemberService.GetByEmail(email);
+ return result == null ? null : new MemberPublishedContent(result, Membership.GetUser(result.Username));
+ }
+
+ #endregion
+
+ #region Model Creation methods for member data editing on the front-end
///
- /// Creates a new profile model filled in with the current members details if they are logged in.
+ /// Creates a new profile model filled in with the current members details if they are logged in which allows for editing
+ /// profile properties
///
///
- public ProfileModel CreateProfileModel()
+ public ProfileModel GetCurrentMemberProfileModel()
{
if (IsLoggedIn() == false)
{
@@ -212,6 +243,7 @@ namespace Umbraco.Web.Security
var model = ProfileModel.CreateModel();
model.Name = member.Name;
+ model.MemberTypeAlias = member.ContentTypeAlias;
model.Email = membershipUser.Email;
model.UserName = membershipUser.UserName;
@@ -225,6 +257,7 @@ namespace Umbraco.Web.Security
model.LastActivityDate = membershipUser.LastActivityDate;
model.LastPasswordChangedDate = membershipUser.LastPasswordChangedDate;
+
var memberType = member.ContentType;
var builtIns = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray();
@@ -287,7 +320,8 @@ namespace Umbraco.Web.Security
model.MemberTypeAlias = string.Empty;
return model;
}
- }
+ }
+ #endregion
///
/// Returns the login status model of the currently logged in member, if no member is logged in it returns null;
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index b74f0f1c14..8397bb332c 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -299,6 +299,8 @@
+
+
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index 6aa2754fbc..10e5ce929f 100644
--- a/src/Umbraco.Web/UmbracoHelper.cs
+++ b/src/Umbraco.Web/UmbracoHelper.cs
@@ -17,6 +17,7 @@ using Umbraco.Core.Xml;
using Umbraco.Web.Models;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
using Umbraco.Web.Templates;
using umbraco;
using System.Collections.Generic;
@@ -35,7 +36,8 @@ namespace Umbraco.Web
{
private readonly UmbracoContext _umbracoContext;
private readonly IPublishedContent _currentPage;
-
+ private readonly MembershipHelper _membershipHelper;
+
///
/// Custom constructor setting the current page to the parameter passed in
///
@@ -46,6 +48,7 @@ namespace Umbraco.Web
{
if (content == null) throw new ArgumentNullException("content");
_currentPage = content;
+ _membershipHelper = new MembershipHelper(_umbracoContext);
}
///
@@ -57,6 +60,7 @@ namespace Umbraco.Web
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
if (umbracoContext.RoutingContext == null) throw new NullReferenceException("The RoutingContext on the UmbracoContext cannot be null");
_umbracoContext = umbracoContext;
+ _membershipHelper = new MembershipHelper(_umbracoContext);
if (_umbracoContext.IsFrontEndUmbracoRequest)
{
_currentPage = _umbracoContext.PublishedContentRequest.PublishedContent;
@@ -405,7 +409,7 @@ namespace Umbraco.Web
{
if (IsProtected(nodeId, path))
{
- return Member.IsLoggedOn() && Access.HasAccess(nodeId, path, Membership.GetUser());
+ return _membershipHelper.IsLoggedIn() && Access.HasAccess(nodeId, path, Membership.GetUser());
}
return true;
}
@@ -416,11 +420,7 @@ namespace Umbraco.Web
/// True is the current user is logged in
public bool MemberIsLoggedOn()
{
- /*
- MembershipUser u = Membership.GetUser();
- return u != null;
- */
- return Member.IsLoggedOn();
+ return _membershipHelper.IsLoggedIn();
}
#endregion
@@ -482,9 +482,51 @@ namespace Umbraco.Web
#endregion
- #region Content
+ #region Members
- public IPublishedContent TypedContent(object id)
+ public IPublishedContent TypedMember(object id)
+ {
+ var asInt = id.TryConvertTo();
+ return asInt ? _membershipHelper.GetById(asInt.Result) : _membershipHelper.GetByProviderKey(id);
+ }
+
+ public IPublishedContent TypedMember(int id)
+ {
+ return _membershipHelper.GetById(id);
+ }
+
+ public IPublishedContent TypedMember(string id)
+ {
+ var asInt = id.TryConvertTo();
+ return asInt ? _membershipHelper.GetById(asInt.Result) : _membershipHelper.GetByProviderKey(id);
+ }
+
+ public dynamic Member(object id)
+ {
+ var asInt = id.TryConvertTo();
+ return asInt
+ ? _membershipHelper.GetById(asInt.Result).AsDynamic()
+ : _membershipHelper.GetByProviderKey(id).AsDynamic();
+ }
+
+ public dynamic Member(int id)
+ {
+ return _membershipHelper.GetById(id).AsDynamic();
+ }
+
+ public dynamic Member(string id)
+ {
+ var asInt = id.TryConvertTo();
+ return asInt
+ ? _membershipHelper.GetById(asInt.Result).AsDynamic()
+ : _membershipHelper.GetByProviderKey(id).AsDynamic();
+ }
+
+ #endregion
+
+ #region Content
+
+ public IPublishedContent TypedContent(object id)
{
return TypedDocumentById(id, _umbracoContext.ContentCache);
}
diff --git a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs
index 9a24e653a3..6a752cdb7a 100644
--- a/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs
+++ b/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs
@@ -645,36 +645,8 @@ namespace umbraco.MacroEngines
private object GetReflectedProperty(string alias)
{
- Func> getMember =
- memberAlias =>
- {
- try
- {
- return Attempt.Succeed(
- n.GetType().InvokeMember(memberAlias,
- System.Reflection.BindingFlags.GetProperty |
- System.Reflection.BindingFlags.Instance |
- System.Reflection.BindingFlags.Public,
- null,
- n,
- null));
- }
- catch (MissingMethodException ex)
- {
- return Attempt.Fail(ex);
- }
- };
-
- //try with the current casing
- var attempt = getMember(alias);
- if (!attempt.Success)
- {
- //if we cannot get with the current alias, try changing it's case
- attempt = alias[0].IsUpperCase()
- ? getMember(alias.ToCleanString(CleanStringType.Ascii | CleanStringType.ConvertCase | CleanStringType.CamelCase))
- : getMember(alias.ToCleanString(CleanStringType.Ascii | CleanStringType.ConvertCase | CleanStringType.PascalCase));
- }
-
+ var attempt = n.GetType().GetMemberIgnoreCase(n, alias);
+
return attempt.Success ? attempt.Result : null;
}