private static void RewriteLinksInArrays(
            IEnumerable <PropertyInfo> arrayProperties,
            object model,
            LinkReWriter rewriter)

        {
            foreach (var arrayProperty in arrayProperties)
            {
                var array = arrayProperty.GetValue(model) as Array ?? new Array[0];

                foreach (var element in array)
                {
                    RewriteAllLinks(element, rewriter);
                }
            }
        }
        private static void RewriteAllLinks(object model, LinkReWriter rewriter)
        {
            if (model == null)
            {
                return;
            }

            var allProperties = model.GetType().GetTypeInfo().GetAllProperties().Where(p => p.CanRead).ToArray();

            var linkProperties = allProperties.Where(p => p.CanWrite && p.PropertyType == typeof(Link));

            foreach (var linkProperty in linkProperties)
            {
                var rewritten = rewriter.Rewrite(linkProperty.GetValue(model) as Link);
                if (rewritten == null)
                {
                    continue;
                }

                linkProperty.SetValue(model, rewritten);

                //sepecial handling of the hidden self property
                //unwrap into the roop object

                if (linkProperty.Name == nameof(Resource.Self))
                {
                    allProperties.SingleOrDefault(p => p.Name == nameof(Resource.Href))
                    ?.SetValue(model, rewritten.Href);

                    allProperties.SingleOrDefault(p => p.Name == nameof(Resource.Method))
                    ?.SetValue(model, rewritten.Method);


                    allProperties.SingleOrDefault(p => p.Name == nameof(Resource.Relations))
                    ?.SetValue(model, rewritten.Relations);
                }
            }

            var arrayProperties = allProperties.Where(p => p.PropertyType.IsArray);

            RewriteLinksInArrays(arrayProperties, model, rewriter);

            var objectProperties = allProperties.Except(linkProperties)
                                   .Except(arrayProperties);

            RewriteLinksInNestedObjects(objectProperties, model, rewriter);
        }
        private static void RewriteLinksInNestedObjects(
            IEnumerable <PropertyInfo> objectProperties,
            object model,
            LinkReWriter rewriter)
        {
            foreach (var objectProperty in objectProperties)
            {
                if (objectProperty.PropertyType == typeof(string))
                {
                    continue;
                }

                var typeInfo = objectProperty.PropertyType.GetTypeInfo();
                if (typeInfo.IsClass)
                {
                    RewriteAllLinks(objectProperty.GetValue(model), rewriter);
                }
            }
        }
        public Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
        {
            var  asObjectResult = context.Result as ObjectResult;
            bool shouldSkip     = asObjectResult?.StatusCode >= 400 || asObjectResult?.Value == null ||
                                  asObjectResult?.Value as Resource == null;

            if (shouldSkip)
            {
                return(next());
            }


            var rewriter = new LinkReWriter(_urlHelperFactory.GetUrlHelper(context));


            RewriteAllLinks(asObjectResult.Value, rewriter);

            return(next());
        }