Less work on non-relative strings in UrlResolutionTagHelper

This commit is contained in:
Ben Adams 2016-02-06 14:01:16 +00:00 committed by N. Taylor Mullen
parent dca15c0a60
commit fd11d70fcd
1 changed files with 96 additions and 38 deletions

View File

@ -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