Giter Site home page Giter Site logo

thenerdery / umbracovault Goto Github PK

View Code? Open in Web Editor NEW
16.0 16.0 6.0 16.34 MB

An easy-to-use, extensible ORM to quickly and easily convert Umbraco documents to C# objects

License: Apache License 2.0

C# 94.91% CSS 0.71% ASP 0.03% HTML 1.38% JavaScript 2.97%

umbracovault's People

Contributors

akatakritos avatar amorger avatar asmorger avatar bitwiseconstructs avatar jaredswarts55 avatar kensykora avatar kluhman avatar nerderymglanzer avatar ptrandem avatar tvanfosson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

umbracovault's Issues

Getting Heterogeneous Children / Ancestors / Descendents

It would be cool to be able to do something like:

Vault.Context.GetAncestors<BaseDocumentViewModel>()
Vault.Context.GetChildren<BaseDocumentViewModel>()
Vault.Context.GetDescendents<BaseDocumentViewModel>()

If you want to get a bunch of documents that inherit from the same document type and share the same base properties.

Mapping Compositions Types

Is it possible map these objects

[UmbracoEntity(AutoMap = true)]
    public class Master
    {   
        public M4_1 M4_1 { get; set; } //composition type
    }
  [UmbracoEntity(AutoMap = true)]
    public class M4_1
    {
        public string Home_M4_Title { get; set; }
}

When I look at my object master m4 is null. If I directly add home_m4_title to master's class it fills it without a problem.

Did I miss something?

The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type '<My Page's Specific View Model>'

@technicallyerik reported this issue:

Hey Guys.

I did a minor refactor to one of my Umbraco Vault applications, and it randomly stops.. "vaulting" after using the website for a little bit.

"The model item passed into the dictionary is of type 'Umbraco.Web.Models.RenderModel', but this dictionary requires a model item of type '<My Page's Specific View Model>'"

It slowly happens one template at a time, but then that template is broken forever until I restart the app pool.

I can't reproduce this corruption consistently. I backed out most of my refactoring I did and it was still happening.

Pulling my hair out. Anything obvious I'm missing before I start digging through every line of Umbraco vault?

unnamed

Properties from interfaces are not automapped

If I have a class with properties derived from an interface, those properties are not automapped.

public Interface INavItem
{
    string Name { get; set; }
}

[UmbracoEntity(Automap = true)]
public class BrokenViewModel : INavItem
{
    public string Name { get; set; }
}

[UmbracoEntity(Automap = true)]
public class WorkingViewModel : INavItem
{
    public string Name { get; set; }

    string INavItem.Name
    {
        get { return Name; }
        set { Name = value; }
    }
}

Doing Vault.Context.GetContentById<BrokenViewModel>(id) will result in Name being null, but Vault.Context.GetContentById<WorkingViewModel>(id) will fix it. Properties not defined in the interface still work as expected.

Multi-Site Get By Document Type

On multi-site instances you might want to get all documents by type, within the site you are currently in. We ended up writing an extension method like this. Worth adding into the core code?

/// <summary>
///     Gets all documents of type T within the current internationalized site
/// </summary>
/// <param name="context">Umbraco context</param>
public static IEnumerable<T> GetByDocumentTypeWithinSite<T>(this IUmbracoContext context)
{
    int rootNode = ResolveRootNodeId(context);

    // Get all documents under the home node with the specified document type
    // Document paths in the Umbraco cache are defined as "-1,<root node>,..."
    var documents = Vault.Context.QueryRelative<T>(
        XpathHelper.GetXpathForDocumentTypeUnderHomeNode(GetUmbracoEntityAliasFromType(typeof(T)), rootNode));

    return documents;
}
/// <summary>
///     Gets the Xpath query for a document type underneith a home node id
/// </summary>
/// <param name="documentTypeId">The document type</param>
/// <param name="homeNodeId">The home node id</param>
public static string GetXpathForDocumentTypeUnderHomeNode(string documentTypeId, int homeNodeId)
{
    return string.Format("//{0}[starts-with(@path, '-1,{1},')]", documentTypeId, homeNodeId);
}

Add Nullable Datetime Handler

Content editors can not enter a date in a date picker, so we should support that.

    /// <summary>
    ///     Handles nullable date picker
    /// </summary>
    public class DateTypeHandler : ITypeHandler
    {
        /// <summary>
        ///     Gets value as a nullable date picker
        /// </summary>
        /// <param name="input">Input to convert to date</param>
        public object GetAsType<T>(object input)
        {
            DateTime result;
            var value = input.ToString();

            if (!DateTime.TryParse(value, out result))
            {
                return null;
            }

            return result == DateTime.MinValue ? (DateTime?)null : result;
        }

        /// <summary>
        ///     Type supported 
        /// </summary>
        public Type TypeSupported
        {
            get { return typeof(DateTime?); }
        }
    }

Error Attempting to Implement Inaccessible Interface

I upgraded Vault from Alpha 1 to Build 43 and get this error:

Type 'Castle.Proxies.BaseViewModelProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is attempting to implement an inaccessible interface.
at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type) at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() at System.Reflection.Emit.TypeBuilder.CreateType() at 
Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType(TypeBuilder type) at 
Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType() at 
Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope) at 
Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory) at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors) at UmbracoVault.Proxy.ProxyInstanceFactory.BuildProxy[T](IPublishedContent node) at UmbracoVault.Proxy.ProxyInstanceFactory.CreateInstance[T](IPublishedContent content) at UmbracoVault.ClassConstructor.CreateWithNode[T](IPublishedContent content) at UmbracoVault.UmbracoWebContext.GetItem[T](IPublishedContent n) at 
UmbracoVault.UmbracoWebContext.GetContentById[T](Int32 id) 

No Umbraco.sdf for Umbraco 7 reference site

I tried copying the database from the Umbraco 6 site, but it threw a bunch of exceptions. I assume its not compatible.

Are you using a different database for the 7 reference site? Could you commit it?

Thanks!

using lazy loading with recursive properties throws a null reference exception when no value is found

With lazy loading enabled, accessing a virtual property annotated with [UmbracoProperty(Recursive = true)] or [UmbracoDataTypeGridProperty(Recursive = true)] when no value is set in the cms throws following exception

[NullReferenceException: Object reference not set to an instance of an object.]
   UmbracoVault.Proxy.ProxyInterceptor.PropertyIsOptedIn(PropertyInfo property) +46
   UmbracoVault.Proxy.ProxyInterceptor.ShouldInterceptMethod(IInvocation invocation, PropertyInfo& property) +102
   UmbracoVault.Proxy.ProxyInterceptor.Intercept(IInvocation invocation) +39
   Castle.DynamicProxy.AbstractInvocation.Proceed() +447
   Castle.Proxies.ContactViewModelProxy.get_InquiryPurposeOptions() +166

Add Generic JSON Data Type Handler

Add a generic type handler to handle any custom Umbraco control that stores JSON data.

    /// <summary>
    ///     Umbraco Vault Type handler for any custom json made data types
    /// </summary>
    /// <typeparam name="T">Model of custom data type</typeparam>
    public class JsonDataTypeHandler<T> : ITypeHandler where T : class, new()
    {
        /// <summary>
        ///     Retrieves the property
        /// </summary>
        /// <typeparam name="T">Not used</typeparam>
        /// <param name="input">Value to be retrieved as model</param>
        /// <returns></returns>
        public object GetAsType<T>(object input)
        {
            return Get(input);
        }

        /// <summary>
        ///     The type supported by the handler
        /// </summary>
        public Type TypeSupported
        {
            get { return typeof(T); }
        }

        /// <summary>
        ///     Converts the data as a given tyoe
        /// </summary>
        /// <param name="data">Data to be converted</param>
        /// <returns></returns>
        private static T Get(object data)
        {
            try
            {
                return data as T ?? JsonConvert.DeserializeObject<T>(data.ToString()) ?? new T();
            }
            catch
            {
                return new T();
            }
        }
    }

Usage:

UmbracoVault.TypeHandlers.TypeHandlerFactory.Instance.RegisterTypeHandler<CustomDataTypeHandler<MyCustomClass>>();

where MyCustomClass is [Serializable]

Normalize Behavior for Inheritence

Currently when an inheritance model is used, behavior within Vault is undefined. For example, for the Castle factory, this test currently passes

        public class InnerClassNoAttributeExtendsBaseClassAutoMap : BaseClassWithAutoMap
        {
            [UmbracoProperty]
            public string Introduction { get; set; }

            [UmbracoProperty]
            public string Body { get; set; }

            [UmbracoProperty]
            public string ImageUrl { get; set; }

            [UmbracoProperty]
            public virtual string ButtonText { get; set; }

            [UmbracoIgnoreProperty]
            public string Ignore1 { get; set; }

            public virtual string Ignore2 { get; set; }
        }

        [UmbracoEntity(AutoMap = true)]
        public class BaseClassWithAutoMap
        {
            public string BaseProperty { get; set; }

            [UmbracoIgnoreProperty]
            public string BaseIgnore { get; set; }

            public virtual string BaseVirtual { get; set; }
        }

        [TestMethod]
        public void GetPropertiesToFill_For_InnerClassNoAttributeExtendsBaseClassAutoMap_ShouldReturnCorrectProperties_WithoutAutomap()
        {
            var properties = _factory.GetPropertiesToFill<InnerClassNoAttributeExtendsBaseClassAutoMap>();
            Assert.AreEqual(4, properties.Count);
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "Introduction"));
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "Body"));
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "ImageUrl"));
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "BaseProperty"));
        }

and for the default factory, this currently is a passing test:

        public class InnerClassNoAttributeExtendsBaseClass : BaseClass
        {
            public string Introduction { get; set; }

            public string Body { get; set; }

            public string ImageUrl { get; set; }

            public virtual string ButtonText { get; set; }

            public string Ignore1 { get; set; }

            public virtual string Ignore2 { get; set; }
        }
   [UmbracoEntity] // AutoMap = False
        public class BaseClass
        {
            [UmbracoProperty]
            public string BaseProperty { get; set; }

            public string BaseIgnore { get; set; }

            [UmbracoProperty]
            public virtual string BaseVirtual { get; set; }
        }
        [TestMethod]
        public void GetPropertiesToFill_For_InnerClassNoAttributeExtendsBaseClass_ShouldReturnCorrectProperties_WithoutAutomap()
        {
            var properties = _factory.GetPropertiesToFill<InnerClassNoAttributeExtendsBaseClass>();
            Assert.AreEqual(2, properties.Count);
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "BaseProperty"));
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "BaseVirtual"));
        }

and on the proxy factory:

        // TODO: Change this behavior later on, probably shouldn't work like this, but retain for now
        // for backewards compatibility
        [TestMethod]
        public void GetPropertiesToFill_For_InnerClassNoAttributeExtendsBaseClass_ShouldReturnCorrectProperties_WithoutAutomap()
        {
            var properties = _factory.GetPropertiesToFill<InnerClassNoAttributeExtendsBaseClass>();
            Assert.AreEqual(1, properties.Count);
            Assert.IsNotNull(properties.FirstOrDefault(p => p.Name == "BaseProperty"));
        }

log4net assembly conflict

Occasionally I get this error in application startup:

System.IO.FileNotFoundException: Could not load file or assembly 'log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a' or one of its dependencies. The system cannot find the file specified.
File name: 'log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a'
   at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
   at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
   at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
   at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType)
   at UmbracoVault.TypeHandlers.TypeHandlerFactory.<GetExternalTypeHandlers>b__0(Assembly x)
   at System.Linq.Enumerable.WhereArrayIterator`1.MoveNext()
   at UmbracoVault.TypeHandlers.TypeHandlerFactory.GetExternalTypeHandlers()
   at UmbracoVault.TypeHandlers.TypeHandlerFactory..ctor()
   at UmbracoVault.TypeHandlers.TypeHandlerFactory.get_Instance()
   at Baker.MvcApplication.RegisterUmbracoVault() in c:\Jenkins\sharedspace\BakerSharedWorkspace\Baker\Global.asax.cs:line 203
   at Baker.MvcApplication.OnApplicationStarting(Object sender, EventArgs e) in c:\Jenkins\sharedspace\BakerSharedWorkspace\Baker\Global.asax.cs:line 62
   at Umbraco.Core.CoreBootManager.Startup(Action`1 afterStartup)
   at Umbraco.Core.UmbracoApplicationBase.StartApplication(Object sender, EventArgs e)

I'm using Umbraco 6.2.5 and Vault 1.1.1, and walked through my entire dependency tree and haven't the faintest idea what references log4net 1.2.13 (everything in my solution is 1.2.11).

Any thoughts?

Feature: Proxy class generation

Like Entity Framework have vault return proxy classes wrapping POCO models. This would enable the following:

  • Lazy mapping from umbraco document to POCO model, just mark properties as virtual.
  • Proxy class generation performs reflection only once per model
  • Opportunity for using proxy classes as AOP layer - logging, caching, etc...

The first item, lazy mapping, is the primary objective. On some projects with tight performance requirements we've found ourselves creating smaller POCOs to reduce mapping overhead in hot spots. Lazy mapping would mean only what is actually used is mapped and would eliminate the need for specialized models. Thinking underlying implementation would use Lazy{T} and do whatever Vault is currently doing now.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.