internal dynamic BuildHypermedia(object model, HttpContext context)
        {
            if (model == null)
            {
                return(null);
            }

            if (model is IEnumerable)
            {
                //how to handle a collection at the root resource level?
                return(((IEnumerable)model).Cast <object>().Select(x => BuildHypermedia(x, context)));
            }

            IDictionary <string, object> halModel = model.ToDynamic();
            var globalTypeConfig = _configuration.GetTypeConfiguration(model.GetType());
            var localTypeConfig  = context.LocalHalConfig().GetTypeConfiguration(model.GetType());

            var typeConfig = new AggregatingHalTypeConfiguration(new List <IHalTypeConfiguration> {
                globalTypeConfig, localTypeConfig
            });

            var links = typeConfig.LinksFor(model, context).ToArray();

            if (links.Any())
            {
                halModel["_links"] = links.GroupBy(l => l.Rel).ToDictionary(grp => grp.Key, grp => BuildDynamicLinksOrLink(grp));
            }

            var embeddedResources = typeConfig.EmbedsFor(model, context).ToArray();

            if (embeddedResources.Any())
            {
                // Remove original objects from the model (if they exist)
                foreach (var embedded in embeddedResources)
                {
                    halModel.Remove(embedded.OriginalPropertyName);
                }
                halModel["_embedded"] = embeddedResources.ToDictionary(info => info.Rel, info => BuildHypermedia(info.GetEmbeddedResource(model), context));
            }

            var ignoredProperties = typeConfig.Ignored().ToArray();

            if (ignoredProperties.Any())
            {
                //remove ignored properties from the output
                foreach (var ignored in ignoredProperties)
                {
                    halModel.Remove(ignored);
                }
            }
            return(halModel);
        }
        public void ShouldAggregateHalTypeConfigurations()
        {
            var typeConfig1 = new HalTypeConfiguration <PetOwner>().Links("rel1", "/staticAddress1");
            var typeConfig2 = new HalTypeConfiguration <PetOwner>().Links("rel2", "/staticAddress2");

            var mergedConfig = new AggregatingHalTypeConfiguration(new List <IHalTypeConfiguration> {
                typeConfig1, typeConfig2
            });

            var config = new MockTypeConfiguration();

            config.Add <PetOwner>(mergedConfig);

            var json = Serialize(new PetOwner {
                Name = "Bob"
            }, config);

            Assert.Equal("Bob", GetStringValue(json, "Name"));
            Assert.Equal("/staticAddress1", GetStringValue(json, "_links", "rel1", "href"));
            Assert.Equal("/staticAddress2", GetStringValue(json, "_links", "rel2", "href"));
        }
        private dynamic BuildHypermedia(object model, NancyContext context)
        {
            if (model == null) return null;

            if (model is IEnumerable)
            {
                //how to handle a collection at the root resource level?
                return ((IEnumerable)model).Cast<object>().Select(x => BuildHypermedia(x, context));
            }

            IDictionary<string, object> halModel = model.ToDynamic();
            var globalTypeConfig = configuration.GetTypeConfiguration(model.GetType());
            var localTypeConfig = context.LocalHalConfig().GetTypeConfiguration(model.GetType());

            var typeConfig = new AggregatingHalTypeConfiguration(new List<IHalTypeConfiguration> { globalTypeConfig, localTypeConfig });

            var links = typeConfig.LinksFor(model, context).ToArray();
            if (links.Any())
                halModel["_links"] = links.GroupBy(l => l.Rel).ToDictionary(grp => grp.Key, grp => BuildDynamicLinksOrLink(grp));

            var embeddedResources = typeConfig.EmbedsFor(model, context).ToArray();
            if (embeddedResources.Any())
            {
                // Remove original objects from the model (if they exist)
                foreach (var embedded in embeddedResources)
                    halModel.Remove(embedded.OriginalPropertyName);
                halModel["_embedded"] = embeddedResources.ToDictionary(info => info.Rel, info => BuildHypermedia(info.GetEmbeddedResource(model), context));
            }

            var ignoredProperties = typeConfig.Ignored().ToArray();
            if (ignoredProperties.Any())
            {
                //remove ignored properties from the output
                foreach (var ignored in ignoredProperties) halModel.Remove(ignored);
            }
            return halModel;
        }
        public void ShouldAggregateHalTypeConfigurations()
        {
            var typeConfig1 = new HalTypeConfiguration<PetOwner>().Links("rel1", "/staticAddress1");
            var typeConfig2 = new HalTypeConfiguration<PetOwner>().Links("rel2", "/staticAddress2");

            var mergedConfig = new AggregatingHalTypeConfiguration(new List<IHalTypeConfiguration> { typeConfig1, typeConfig2 });

            var config = new MockTypeConfiguration();
            config.Add<PetOwner>(mergedConfig);

            var json = Serialize(new PetOwner { Name = "Bob" }, config);

            Assert.Equal("Bob", GetStringValue(json, "Name"));
            Assert.Equal("/staticAddress1", GetStringValue(json, "_links", "rel1", "href"));
            Assert.Equal("/staticAddress2", GetStringValue(json, "_links", "rel2", "href"));
        }