private void Initialize() { // Initialize stuff for the Uri template Regex newFromRegex = null; this._uriRegexIdentifierUsedTwice = this.UriTemplateContainsSameIdentifierTwice(this._uri, out newFromRegex); this._uriHasQueryString = !String.IsNullOrEmpty(UriParsingHelper.InternalUriGetQueryString(this._uri)); this._uriHasFragment = !String.IsNullOrEmpty(UriParsingHelper.InternalUriGetFragment(this._uri)); this._uriRegex = newFromRegex; this._mappedUriIsOnlyFragment = UriParsingHelper.InternalUriIsFragment(this._mappedUri); this._mappedUriIsOnlyQueryString = UriParsingHelper.QueryStringDelimiter + UriParsingHelper.InternalUriGetQueryString(this._mappedUri) == this._mappedUri.OriginalString; // Initialize stuff for the mapped Uri template this.GetIdentifiersForMappedUri(this._mappedUri); this._initialized = true; }
private void CompleteNavigation(DependencyObject content) { Uri uri = null; string pageTitle = null; Page existingContentPage = this._host.Content as Page; Page newContentPage = content as Page; pageTitle = JournalEntry.GetName(content ?? this._host.Content as DependencyObject); NavigationOperation navOp = this._currentNavigation; this._currentNavigation = null; if (navOp != null) { // Set uri uri = navOp.UriBeforeMapping; // Used to suppress navigation notifications. navOp.SuppressNotifications = true; if (this.CurrentSource == navOp.UriForJournal) { // Do not record the navigation in the journal when moving to the same URI whether this // is a redirection or not. navOp.SuppressJournalAdd = true; } this.CurrentSource = navOp.UriForJournal; this._source = navOp.UriBeforeMapping; this._currentSourceAfterMapping = navOp.Uri; this.Host.UpdateSourceFromNavigationService(navOp.UriForJournal); this.Host.CurrentSource = this.CurrentSource; // Check if this is a 'New' operation if (navOp.Mode == NavigationMode.New && navOp.Uri != null && navOp.SuppressJournalAdd == false) { try { this._journalIsAddingHistoryPoint = true; JournalEntry je = new JournalEntry(pageTitle ?? uri.OriginalString, navOp.UriForJournal); this.Journal.AddHistoryPoint(je); } finally { this._journalIsAddingHistoryPoint = false; } } this.Host.CanGoBack = this.CanGoBack; this.Host.CanGoForward = this.CanGoForward; navOp.SuppressNotifications = false; } if (this.Journal.UseNavigationState && HtmlPage.IsEnabled) { HtmlPage.Document.SetProperty("title", pageTitle ?? (uri == null ? string.Empty : uri.OriginalString)); } if (content == null) { // We're navigating to a fragment in the current page, so for WPF compatibility, fire FragmentNavigation THEN Navigated if (navOp != null) { this.RaiseFragmentNavigation(UriParsingHelper.InternalUriGetFragment(navOp.Uri)); this.RaiseNavigated(content, uri, existingContentPage, newContentPage); } } else { // We're navigating to a fragment in the new content, so let the host load content, then for WPF compatibility, // fire Navigated THEN FragmentNavigation this.Host.Content = content; this.RaiseNavigated(content, uri, existingContentPage, newContentPage); string fragment = navOp == null ? null : UriParsingHelper.InternalUriGetFragment(navOp.Uri); if (!String.IsNullOrEmpty(fragment)) { this.RaiseFragmentNavigation(fragment); } } }
/// <summary> /// Attempts to process a Uri, if it matches the Uri template /// </summary> /// <param name="uri">The Uri to map</param> /// <returns>The Uri after mapping, or null if mapping did not succeed</returns> public Uri MapUri(Uri uri) { this.CheckPreconditions(); if (this._uriRegex == null) { // If an empty Uri was passed in, we can map that even with an empty Uri Template. if (uri == null || uri.OriginalString == null || uri.OriginalString.Length == 0) { return new Uri(this._mappedUri.OriginalString, UriKind.Relative); } // Otherwise, this does not match anything else { return null; } } string originalUriWithoutQueryString = UriParsingHelper.InternalUriGetBaseValue(uri); Match m = this._uriRegex.Match(originalUriWithoutQueryString); if (!m.Success) { return null; } string uriAfterMappingBase = UriParsingHelper.InternalUriGetBaseValue(this._mappedUri); IDictionary<string, string> uriAfterMappingQueryString = UriParsingHelper.InternalUriParseQueryStringToDictionary(this._mappedUri, false /* decodeResults */); IDictionary<string, string> originalQueryString = UriParsingHelper.InternalUriParseQueryStringToDictionary(uri, false /* decodeResults */); string originalFragment = UriParsingHelper.InternalUriGetFragment(uri); string uriAfterMappingFragment = UriParsingHelper.InternalUriGetFragment(this._mappedUri); // 'uriValues' is the values of the identifiers from the 'Uri' template, as they appear in the Uri // being processed IDictionary<string, string> uriValues = new Dictionary<string, string>(); // i begins at 1 because the group at index 0 is always equal to the parent's Match, // which we do not want. We only want explicitly-named groups. int groupCount = m.Groups.Count; for (int i = 1; i < groupCount; i++) { uriValues.Add(this._uriRegex.GroupNameFromNumber(i), m.Groups[i].Value); } foreach (string identifier in this._mappedUriIdentifiers) { string identifierWithBraces = "{" + identifier + "}"; string replacementValue = (uriValues.ContainsKey(identifier) ? uriValues[identifier] : String.Empty); // First check for identifiers in the base Uri, and replace them as appropriate uriAfterMappingBase = uriAfterMappingBase.Replace(identifierWithBraces, replacementValue); // Then, look through the query string (both the key and the value) and replace as appropriate string[] keys = new string[uriAfterMappingQueryString.Keys.Count]; uriAfterMappingQueryString.Keys.CopyTo(keys, 0); foreach (string key in keys) { // First check if the value contains it, as this is an easy replacement if (uriAfterMappingQueryString[key].Contains(identifierWithBraces)) { if (uriValues.ContainsKey(identifier)) { uriAfterMappingQueryString[key] = uriAfterMappingQueryString[key].Replace(identifierWithBraces, replacementValue); } } // If the key itself contains the identifier, then we need to remove the existing item with the key that // contains the identifier, and re-add to the dictionary with the new key and the pre-existing value if (key.Contains(identifierWithBraces)) { string existingVal = uriAfterMappingQueryString[key]; uriAfterMappingQueryString.Remove(key); uriAfterMappingQueryString.Add(key.Replace(identifierWithBraces, replacementValue), existingVal); } } // If there's an original fragment already present, it will always win, so don't bother doing replacements if (String.IsNullOrEmpty(originalFragment) && !String.IsNullOrEmpty(uriAfterMappingFragment)) { if (uriAfterMappingFragment.Contains(identifierWithBraces)) { uriAfterMappingFragment = uriAfterMappingFragment.Replace(identifierWithBraces, replacementValue); } } } foreach (string key in originalQueryString.Keys) { if (!uriAfterMappingQueryString.ContainsKey(key)) { uriAfterMappingQueryString.Add(key, originalQueryString[key]); } else { // If a value is present in the originally-navigated-to query string, it // takes precedence over anything in the aliased query string by default. uriAfterMappingQueryString[key] = originalQueryString[key]; } } if (!String.IsNullOrEmpty(originalFragment)) { uriAfterMappingFragment = originalFragment; } return UriParsingHelper.InternalUriCreateWithQueryStringValues(uriAfterMappingBase, uriAfterMappingQueryString, uriAfterMappingFragment); }