Less work on non-relative strings in UrlResolutionTagHelper
This commit is contained in:
parent
dca15c0a60
commit
fd11d70fcd
|
|
@ -219,23 +219,18 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
protected bool TryResolveUrl(string url, out string resolvedUrl)
|
protected bool TryResolveUrl(string url, out string resolvedUrl)
|
||||||
{
|
{
|
||||||
resolvedUrl = null;
|
resolvedUrl = null;
|
||||||
if (url == null)
|
var start = FindRelativeStart(url);
|
||||||
|
if (start == -1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var trimmedUrl = url.Trim(ValidAttributeWhitespaceChars);
|
var trimmedUrl = CreateTrimmedString(url, start);
|
||||||
|
|
||||||
// Before doing more work, ensure that the URL we're looking at is app-relative.
|
var urlHelper = UrlHelperFactory.GetUrlHelper(ViewContext);
|
||||||
if (trimmedUrl.Length >= 2 && trimmedUrl[0] == '~' && trimmedUrl[1] == '/')
|
resolvedUrl = urlHelper.Content(trimmedUrl);
|
||||||
{
|
|
||||||
var urlHelper = UrlHelperFactory.GetUrlHelper(ViewContext);
|
|
||||||
resolvedUrl = urlHelper.Content(trimmedUrl);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -250,41 +245,104 @@ namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
|
||||||
protected bool TryResolveUrl(string url, out IHtmlContent resolvedUrl)
|
protected bool TryResolveUrl(string url, out IHtmlContent resolvedUrl)
|
||||||
{
|
{
|
||||||
resolvedUrl = null;
|
resolvedUrl = null;
|
||||||
if (url == null)
|
var start = FindRelativeStart(url);
|
||||||
|
if (start == -1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var trimmedUrl = url.Trim(ValidAttributeWhitespaceChars);
|
var trimmedUrl = CreateTrimmedString(url, start);
|
||||||
|
|
||||||
// Before doing more work, ensure that the URL we're looking at is app-relative.
|
var urlHelper = UrlHelperFactory.GetUrlHelper(ViewContext);
|
||||||
if (trimmedUrl.Length >= 2 && trimmedUrl[0] == '~' && trimmedUrl[1] == '/')
|
var appRelativeUrl = urlHelper.Content(trimmedUrl);
|
||||||
|
var postTildeSlashUrlValue = trimmedUrl.Substring(2);
|
||||||
|
|
||||||
|
if (!appRelativeUrl.EndsWith(postTildeSlashUrlValue, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var urlHelper = UrlHelperFactory.GetUrlHelper(ViewContext);
|
throw new InvalidOperationException(
|
||||||
var appRelativeUrl = urlHelper.Content(trimmedUrl);
|
Resources.FormatCouldNotResolveApplicationRelativeUrl_TagHelper(
|
||||||
var postTildeSlashUrlValue = trimmedUrl.Substring(2);
|
url,
|
||||||
|
nameof(IUrlHelper),
|
||||||
if (!appRelativeUrl.EndsWith(postTildeSlashUrlValue, StringComparison.Ordinal))
|
nameof(IUrlHelper.Content),
|
||||||
{
|
"removeTagHelper",
|
||||||
throw new InvalidOperationException(
|
typeof(UrlResolutionTagHelper).FullName,
|
||||||
Resources.FormatCouldNotResolveApplicationRelativeUrl_TagHelper(
|
typeof(UrlResolutionTagHelper).GetTypeInfo().Assembly.GetName().Name));
|
||||||
url,
|
|
||||||
nameof(IUrlHelper),
|
|
||||||
nameof(IUrlHelper.Content),
|
|
||||||
"removeTagHelper",
|
|
||||||
typeof(UrlResolutionTagHelper).FullName,
|
|
||||||
typeof(UrlResolutionTagHelper).GetTypeInfo().Assembly.GetName().Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvedUrl = new EncodeFirstSegmentContent(
|
|
||||||
appRelativeUrl,
|
|
||||||
appRelativeUrl.Length - postTildeSlashUrlValue.Length,
|
|
||||||
postTildeSlashUrlValue);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
resolvedUrl = new EncodeFirstSegmentContent(
|
||||||
|
appRelativeUrl,
|
||||||
|
appRelativeUrl.Length - postTildeSlashUrlValue.Length,
|
||||||
|
postTildeSlashUrlValue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int FindRelativeStart(string url)
|
||||||
|
{
|
||||||
|
if (url == null || url.Length < 2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxTestLength = url.Length - 2;
|
||||||
|
|
||||||
|
var start = 0;
|
||||||
|
for (; start < url.Length; start++)
|
||||||
|
{
|
||||||
|
if (start > maxTestLength)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsCharWhitespace(url[start]))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before doing more work, ensure that the URL we're looking at is app-relative.
|
||||||
|
if (url[start] != '~' || url[start + 1] != '/')
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateTrimmedString(string input, int start)
|
||||||
|
{
|
||||||
|
var end = input.Length - 1;
|
||||||
|
for (; end >= start; end--)
|
||||||
|
{
|
||||||
|
if (!IsCharWhitespace(input[end]))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var len = end - start + 1;
|
||||||
|
|
||||||
|
// Substring returns same string if start == 0 && len == Length
|
||||||
|
return input.Substring(start, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsCharWhitespace(char ch)
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
for (; i < ValidAttributeWhitespaceChars.Length; i++)
|
||||||
|
{
|
||||||
|
if (ValidAttributeWhitespaceChars[i] == ch)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ValidAttributeWhitespaceChars.Length)
|
||||||
|
{
|
||||||
|
// the character is not white space
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EncodeFirstSegmentContent : IHtmlContent
|
private class EncodeFirstSegmentContent : IHtmlContent
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue