コード例 #1
0
        /// <inheritdoc />
        public string CreateUrl(ApiOperationLink link, object result = null)
        {
            // This duplicates the checks in CreateRelativeUrlFromLink for the purpose of not creating a new instance
            // of StringBuilder unnecessarily
            if (result == null)
            {
                return(this._baseUri + link.UrlFormat);
            }

            // We can short-circuit in the (relatively uncommon case) of no placeholders
            if (!link.HasPlaceholders())
            {
                return(this._baseUri + link.UrlFormat);
            }

            var relativeUrl = CreateRelativeUrlFromLink(link, result);

            // We cannot create a full URL if the relative link is null
            if (relativeUrl == null)
            {
                return(null);
            }

            // baseUri always has / at end, relative never has at start
            return(this._baseUri + relativeUrl);
        }
コード例 #2
0
            public void When_Url_With_Simple_Placeholder_Then_CreateUrl_Replaces_With_Property_In_PropValues()
            {
                // Act
                var link = new ApiOperationLink(descriptor, "/aUrl/{category}", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new { category = "cats" }).Should().EndWith("aUrl/cats");
            }
コード例 #3
0
            public void When_Placeholder_Specifies_Alternate_Property_And_Followed_By_Another_Placeholder_Then_Uses_That_Property_From_Instance_Values()
            {
                // Act
                var link = new ApiOperationLink(descriptor, "/aUrl/{clientid:id}/{category}", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new { id = 15484, category = "value" }).Should().EndWith("aUrl/15484/value");
            }
コード例 #4
0
            public void When_Placeholder_Followed_By_Static_Then_Includes_All()
            {
                // Act
                var link = new ApiOperationLink(descriptor, "/aUrl/{clientid:id}/some-more", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new { id = 15484 }).Should().EndWith("aUrl/15484/some-more");
            }
コード例 #5
0
            public void When_Url_With_Placeholder_Requiring_Encoding_Then_CreateUrl_Replaces_With_Encoded_Property_In_PropValues()
            {
                // Act
                var link = new ApiOperationLink(descriptor, "/aUrl/{category}", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new { category = "all dogs" }).Should().EndWith("aUrl/all%20dogs");
            }
コード例 #6
0
            public void When_AbsoluteUrl_Prepends_Configuration_Base_Url()
            {
                // Arrange
                var link = new ApiOperationLink(descriptor, "/aUrl", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new object()).Should().Be("http://api.example.com/api/aUrl");
            }
コード例 #7
0
            public void When_Url_With_Placeholder_Then_Returns_Null_If_Property_Is_Null()
            {
                // Act
                var link = new ApiOperationLink(descriptor, "/aUrl/{category}", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new { category = (string)null }).Should().BeNull();
            }
コード例 #8
0
            public void When_Url_No_Placeholders_CreateUrl_Returns_Url_As_Is()
            {
                // Arrange
                var link = new ApiOperationLink(descriptor, "/aUrl", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new object()).Should().EndWith("aUrl");
            }
コード例 #9
0
        public void When_Additional_Properties_Exists_Ignore_When_IncludeExtra_False()
        {
            // Act
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/users", "a.rel");

            // Assert
            link.CreateRelativeUrl(new { sortBy = "name", page = 2 }, false).Should().Be("users");
        }
コード例 #10
0
        public void When_Placeholder_Followed_By_Static_Then_Includes_All()
        {
            // Act
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/aUrl/{clientid:id}/some-more", "a.rel");

            // Assert
            link.CreateRelativeUrl(new { id = 15484 }).Should().EndWith("aUrl/15484/some-more");
        }
コード例 #11
0
            public void When_Placeholder_Has_Format_Then_CreateUrl_Uses_Format()
            {
                // Act
                var date = new DateTime(2012, 04, 21);
                var link = new ApiOperationLink(descriptor, "/aUrl/{date(yyyy-MM-dd)}", "a.rel");

                // Assert
                linkGenerator.CreateUrl(link, new { date }).Should().EndWith("aUrl/2012-04-21");
            }
コード例 #12
0
        public void When_Placeholder_Specifies_Alternate_Property_Then_Uses_That_Property_From_Instance_Values()
        {
            // Act
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/aUrl/{clientid:id}", "a.rel");

            // Assert
            link.CreateRelativeUrl(new { id = 15484 }).Should().EndWith("aUrl/15484");
        }
コード例 #13
0
        public void When_Url_With_Placeholder_Then_Returns_Null_If_Property_Is_Null()
        {
            // Act
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/aUrl/{category}", "a.rel");

            // Assert
            link.CreateRelativeUrl(new { category = (string)null }).Should().BeNull();
        }
コード例 #14
0
        public void When_Url_With_Simple_Placeholder_Then_CreateUrl_Replaces_With_Property_In_PropValues()
        {
            // Act
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/aUrl/{category}", "a.rel");

            // Assert
            link.CreateRelativeUrl(new { category = "cats" }).Should().EndWith("aUrl/cats");
        }
コード例 #15
0
        public void When_Url_No_Placeholders_CreateUrl_Returns_Url_As_Is()
        {
            // Arrange
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/aUrl", "a.rel");

            // Assert
            link.CreateRelativeUrl(new object()).Should().EndWith("aUrl");
        }
コード例 #16
0
        public void When_Placeholder_Has_Alternate_Name_Then_RoutingUrl_Strips()
        {
            // Arrange
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");

            // Act
            var link = new ApiOperationLink(descriptor, "/aUrl/{ClientId:Id}", "a.rel");

            // Assert
            link.RoutingUrl.Should().Be("aUrl/{ClientId}");
        }
コード例 #17
0
        public void When_Placeholder_Has_Different_Case_RoutingUrl_Should_Normalise()
        {
            // Arrange
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");

            // Act
            var link = new ApiOperationLink(descriptor, "/aUrl/{clientId:Id}", "a.rel");

            // Assert
            link.RoutingUrl.Should().Be("aUrl/{ClientId}");
        }
コード例 #18
0
        public void When_Format_Has_QueryString_RoutingUrl_Strips()
        {
            // Arrange
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");

            // Act
            var link = new ApiOperationLink(descriptor, "/aUrl/{clientid:id}?format=pdf", "a.rel");

            // Assert
            link.RoutingUrl.Should().Be("aUrl/{ClientId}");
        }
コード例 #19
0
        public void When_Created_Then_Exposes_Rel_Property()
        {
            // Arrange
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");

            // Act
            var link = new ApiOperationLink(descriptor, "/aUrl", "a.rel");

            // Assert
            link.Rel.Should().Be("a.rel");
        }
コード例 #20
0
        public void When_Placeholder_Has_Alternate_Name_Then_Placeholder_Created_With_AlternatePropertyName()
        {
            // Arrange
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");

            // Act
            var link = new ApiOperationLink(descriptor, "/aUrl/{ClientId:Id}", "a.rel");

            // Assert
            link.Placeholders[0].AlternatePropertyName.Should().Be("Id");
            link.Placeholders[0].OriginalText.Should().Be("{ClientId:Id}");
            link.Placeholders[0].Property.Name.Should().Be("ClientId");
            link.Placeholders[0].Format.Should().BeNull();
        }
コード例 #21
0
        public void When_Additional_Properties_And_Placeholders_Exists_Adds_As_QueryString_When_IncludeExtra_True()
        {
            // Act
            var descriptor = new ApiOperationDescriptor(typeof(LinkGeneratorTestsOperation), "tests");
            var link       = new ApiOperationLink(descriptor, "/clients/{clientId}/users", "a.rel");

            // Act
            var url = link.CreateRelativeUrl(new LinkGeneratorTestsOperation {
                ClientId = 12, SortBy = "name", Page = 2
            }, true);

            // Assert
            url.Should().Be("clients/12/users?SortBy=name&Page=2");
        }
コード例 #22
0
        /// <inheritdoc />
        public string CreateUrl(ApiOperationLink link, object result = null)
        {
            // We can short-circuit in the (relatively uncommon case) of no placeholders
            if (!link.HasPlaceholders())
            {
                return(this._baseUri + link.UrlFormat);
            }

            var relativeUrl = link.CreateRelativeUrl(result);

            // We cannot create a full URL if the relative link is null
            if (relativeUrl == null)
            {
                return(null);
            }

            // baseUri always has / at end, relative never has at start
            return(this._baseUri + relativeUrl);
        }
コード例 #23
0
        private static StringBuilder CreateRelativeUrlFromLink(ApiOperationLink link, object result)
        {
            if (result == null)
            {
                return(new StringBuilder(link.UrlFormat));
            }

            // We can short-circuit in the (relatively uncommon case) of no placeholders
            if (!link.HasPlaceholders())
            {
                return(new StringBuilder(link.UrlFormat));
            }

            var builtUrl     = new StringBuilder();
            var currentIndex = 0;

            foreach (var placeholder in link.Placeholders)
            {
                // Grab the static bit of the URL _before_ this placeholder.
                builtUrl.Append(link.UrlFormat.Substring(currentIndex, placeholder.Index - currentIndex));

                // Now skip over the actual placeholder for the next iteration
                currentIndex = placeholder.Index + placeholder.Length;

                object placeholderValue;

                if (link.OperationDescriptor.OperationType == result.GetType())
                {
                    // Do not have to deal with "alternate" names, we know the original name is correct
                    placeholderValue = placeholder.Property.GetValue(result);
                }
                else
                {
                    // We cannot use the existing PropertyInfo on placeholder because the type is different, even though they are the same name
                    var property = result
                                   .GetType()
                                   .GetProperty(placeholder.AlternatePropertyName ?? placeholder.Property.Name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);

                    if (property == null)
                    {
                        if (placeholder.AlternatePropertyName != null)
                        {
                            throw new InvalidOperationException(
                                      $"Cannot find property '{placeholder.AlternatePropertyName}' (specified as alternate name) on type '{result.GetType()}'");
                        }

                        throw new InvalidOperationException(
                                  $"Cannot find property '{placeholder.Property.Name}' on type '{result.GetType()}'");
                    }

                    placeholderValue = property.GetValue(result);
                }

                // If we have a placeholder value then we must return null if it does not exist, otherwise we would build URLs
                // like /users/null if using a "safe" representation
                if (placeholderValue == null)
                {
                    return(null);
                }

                if (placeholder.Format != null)
                {
                    builtUrl.Append(Uri.EscapeDataString(string.Format(placeholder.FormatSpecifier, placeholderValue)));
                }
                else
                {
                    // We do not have a format so just ToString the result. We pick a few common types to cast directly to avoid indirect
                    // call to ToString when doing it as (object).ToString()
                    switch (placeholderValue)
                    {
                    case string s:
                        builtUrl.Append(Uri.EscapeDataString(s));
                        break;

                    case Guid g:
                        builtUrl.Append(Uri.EscapeDataString(g.ToString()));
                        break;

                    case int i:
                        builtUrl.Append(Uri.EscapeDataString(i.ToString()));
                        break;

                    case long l:
                        builtUrl.Append(Uri.EscapeDataString(l.ToString()));
                        break;

                    default:
                        builtUrl.Append(Uri.EscapeDataString(placeholderValue.ToString()));
                        break;
                    }
                }
            }

            if (currentIndex < link.UrlFormat.Length)
            {
                builtUrl.Append(link.UrlFormat.Substring(currentIndex));
            }

            return(builtUrl);
        }