/// <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); }
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"); }
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"); }
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"); }
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"); }
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"); }
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(); }
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"); }
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"); }
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"); }
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"); }
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"); }
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(); }
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"); }
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"); }
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}"); }
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}"); }
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}"); }
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"); }
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(); }
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"); }
/// <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); }
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); }