private bool TryResolveRoute(ref string path, out Page page)
{
if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1);
if(path == "")
{
if(defaultRoute.HasValue)
{
path = defaultRoute.Value.Key;
page = defaultRoute.Value.Value();
page.RouteVariables = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>());
page.Path = defaultRoute.Value.Key;
return true;
}
else
{
page = null;
return false;
}
}
var pathSegments = path.Split('/');
foreach (var route in routes.Keys)
{
var variablesCandidate = new Dictionary<string, string>();
var routeSegments = route.Split('/');
if(pathSegments.Length == routeSegments.Length)
{
// the path and route has the same # of segments
}
else if(routeSegments.Length > pathSegments.Length)
{
// path can't match route because the path is too short, skip it
continue;
}
else if(pathSegments.Length > routeSegments.Length && route.Contains("{*}"))
{
// this route supports dynamic routing so it's ok to keep checking if the path is longer than the route
}
else
{
continue;
}
bool candidateIsGood = true;
for(int i = 0; i < routeSegments.Length; i++)
{
var routeSegment = routeSegments[i];
var pathSegment = pathSegments[i];
if(routeSegment.StartsWith("{") && routeSegment.EndsWith("}"))
{
var variableName = routeSegment.Substring(1, routeSegment.Length - 2);
if (variableName == "*")
{
var restOfPathValue = "";
for(int j = i; j < pathSegments.Length; j++)
{
restOfPathValue += pathSegments[j]+"/";
}
restOfPathValue = restOfPathValue.Substring(0, restOfPathValue.Length - 1);
variablesCandidate.Add(variableName, restOfPathValue);
break;
}
else
{
variablesCandidate.Add(variableName, pathSegment);
}
}
else if(routeSegment.Equals(pathSegment, StringComparison.InvariantCultureIgnoreCase) == false)
{
candidateIsGood = false;
break;
}
}
if(candidateIsGood)
{
page = routes[route]();
page.RouteVariables = new ReadOnlyDictionary<string, string>(variablesCandidate);
page.Path = path;
return true;
}
}
page = null;
return false;
}