/// <summary>
		/// Add a new QueryString segment to a UrlDetails instance if the specified value is defined (if a Missing value is provided then the source UrlDetails instance will be returned unaltered).
		/// The value will have ToString called on it to generate the QueryString segment value. This will throw an exception for a null source or null-or-blank-or-whitespace-only key.
		/// </summary>
		public static UrlDetails AddToQueryIfDefined<T>(this UrlDetails source, string key, Optional<T> value)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (string.IsNullOrWhiteSpace(key))
				throw new ArgumentException($"Null/blank {nameof(key)} specified");

			return value.IsDefined ? AddToQuery(source, key, value.Value) : source;
		}
예제 #2
0
                public bool ExecuteCallbackIfUrlMatches(UrlDetails url)
                {
                    if (url == null)
                    {
                        throw new ArgumentNullException("url");
                    }

                    if (url.Segments.Count != _segmentMatchers.Count)
                    {
                        return(false);
                    }

                    var valuesExtractedFromMatchedVariables = NonNullList <object> .Empty;

                    foreach (var segmentAndMatcher in url.Segments.Zip(_segmentMatchers, (segment, matcher) => new { Segment = segment, Matcher = matcher }))
                    {
                        var matchResult = segmentAndMatcher.Matcher.Match(segmentAndMatcher.Segment);
                        if (!matchResult.IsDefined)
                        {
                            return(false);
                        }

                        if (matchResult.Value.ValueExtractedFromVariableSegment.IsDefined)
                        {
                            valuesExtractedFromMatchedVariables = valuesExtractedFromMatchedVariables.Add(matchResult.Value.ValueExtractedFromVariableSegment.Value);
                        }
                    }
                    if (!valuesExtractedFromMatchedVariables.Any())
                    {
                        // The VariableRouteDetails class should only be used if there is at least one variable url segment to match, otherwise the StaticRouteDetails would be
                        // more sensible. Since both VariableRouteDetails and StaticRouteDetails are private and may only be instantiated by the RouteBuilder, there is no way
                        // that we should find ourselves here with no variable segments to process.
                        throw new Exception("This shouldn't happen because.. ");
                    }

                    // Note: The number of segments that the extractedValueBuilder expects should be consistent with the number of matchedVariables (this is always the case for
                    // VariableRouteDetails instances created by the RouteBuilder which means that it should always be the general case since VariableRouteDetails is a private
                    // class and may not be instantiated by anything other than the RouteBuilder)
                    TValues extractedValue;

                    if (_extractedValueBuilder.IsDefined)
                    {
                        extractedValue = _extractedValueBuilder.Value(valuesExtractedFromMatchedVariables);
                    }
                    else
                    {
                        // If there's no _extractedValueBuilder then no-one cares about what's matched here, so we can set extractedValue to null (we have to use Script.Write
                        // because we can't be sure that TValues is not a value type and we can't set it to default(TValues) because we don't have access to the TValues type
                        // at runtime because this class is decorated with [IgnoreGeneric]
                        extractedValue = Script.Write <TValues>("null");
                    }
                    _ifMatched(extractedValue, url.QueryString);
                    return(true);
                }
        private void RaiseCallbacks(UrlDetails url)
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            foreach (var callback in _navigatedCallbacks)
            {
                callback(url);
            }
        }
예제 #4
0
 public Link(
     UrlDetails url,
     ReactElement text,
     bool caseSensitiveUrlMatching           = false,
     Optional <NonBlankTrimmedString> name   = new Optional <NonBlankTrimmedString>(),
     Optional <NonBlankTrimmedString> target = new Optional <NonBlankTrimmedString>(),
     Optional <ClassName> className          = new Optional <ClassName>(),
     Optional <ClassName> ancestorClassName  = new Optional <ClassName>(),
     Optional <ClassName> selectedClassName  = new Optional <ClassName>(),
     Optional <Action <MouseEvent <Bridge.Html5.HTMLAnchorElement> > > onClick = new Optional <Action <MouseEvent <Bridge.Html5.HTMLAnchorElement> > >(),
     Optional <IInteractWithBrowserRouting> historyHandlerOverride             = new Optional <IInteractWithBrowserRouting>())
     : base(new Props(url, text, caseSensitiveUrlMatching, name, target, className, ancestorClassName, selectedClassName, onClick, historyHandlerOverride))
 {
 }
		/// <summary>
		/// Add a new QueryString segment to a UrlDetails instance. The value will have ToString called on it to generate the QueryString segment value. This will throw an exception for a null source, a
		/// null-or-blank-or-whitespace-only key or a null value.
		/// </summary>
		public static UrlDetails AddToQuery(this UrlDetails source, string key, object value)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));
			if (string.IsNullOrWhiteSpace(key))
				throw new ArgumentException($"Null/blank {nameof(key)} specified");
			if (value == null)
				throw new ArgumentNullException(nameof(value));

			// 2019-01-08: Unless/until https://forums.bridge.net/forum/community/help/6001 is accepted as a bug and fixed, we can't rely upon the ToString implementation of
			// NonBlankTrimmedString since it became annotated with [ObjectLiteral] (for deserialisation performance improvements) - ObjectLiteralToStringSupport is required 
			return new UrlDetails(
				source.Segments,
				source.QueryString.GetValueOrDefault(new QueryString(NonNullList<QueryString.Segment>.Empty)).Add(key, ObjectLiteralToStringSupport.ToString(value))
			);
		}
        public void NavigateTo(UrlDetails url)
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            // 2017-12-08 DWR: Since navigations fire Dispatcher actions, it means that there will be difficulties if using a Dispatcher which does not allow the handling of one action to dispatch
            // another action (which is something that recommended by Facebook - to not let one action fire another because this could lead to a difficult-to-reason-about chain of events) if you
            // want to have a successful update send the User to a success page (because the update-successfully-applied action would cause a navigation, which would dispatch another action).
            // As a workaround (which, granted, feels a little dirty), we'll apply a SetTimeout to the history manipulation to "break" the potential Dispatcher action chain. This doesn't feel
            // SO filthy since requesting a location change and waiting for the browser to apply it and a corresponding Dispatcher method to be fired could understandably be an async process..
            // though, really, we only want this for convenience.
            Window.SetTimeout(() =>
            {
                LastNavigatedToUrl = GetCurrentLocation();
                Window.History.PushState(state: null, title: null, url: url.ToString());
                RaiseCallbacks(url);
            });
        }
예제 #7
0
            public bool ExecuteCallbackIfUrlMatches(UrlDetails url)
            {
                if (url == null)
                {
                    throw new ArgumentNullException("url");
                }

                if (url.Segments.Count != _segments.Count)
                {
                    return(false);
                }

                if (url.Segments.Zip(_segments, (x, y) => x.Value.Equals(y.Value, StringComparison.OrdinalIgnoreCase)).Any(isMatch => !isMatch))
                {
                    return(false);
                }

                _ifMatched(url.QueryString);
                return(true);
            }
예제 #8
0
 public Props(
     UrlDetails url,
     Union <ReactElement, string> text,
     bool caseSensitiveUrlMatching,
     Optional <NonBlankTrimmedString> name,
     Optional <NonBlankTrimmedString> target,
     Optional <ClassName> className,
     Optional <ClassName> ancestorClassName,
     Optional <ClassName> selectedClassName,
     Optional <Action <MouseEvent <Bridge.Html5.HTMLAnchorElement> > > onClick,
     Optional <IInteractWithBrowserRouting> historyHandlerOverride)
 {
     this.CtorSet(_ => _.Url, url);
     this.CtorSet(_ => _.Text, text);
     this.CtorSet(_ => _.CaseSensitiveUrlMatching, caseSensitiveUrlMatching);
     this.CtorSet(_ => _.Name, name);
     this.CtorSet(_ => _.Target, target);
     this.CtorSet(_ => _.ClassName, className);
     this.CtorSet(_ => _.AncestorClassName, ancestorClassName);
     this.CtorSet(_ => _.SelectedClassName, selectedClassName);
     this.CtorSet(_ => _.OnClick, onClick);
     this.CtorSet(_ => _.HistoryHandlerOverride, historyHandlerOverride);
 }
        private static void MatchRoute(UrlDetails url, NonNullList <IMatchRoutes> routes, Optional <Action <UrlPathDetails> > routeNotMatched)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }
            if (routes == null)
            {
                throw new ArgumentNullException(nameof(routes));
            }

            foreach (var route in routes)
            {
                if (route.ExecuteCallbackIfUrlMatches(url))
                {
                    return;
                }
            }
            if (routeNotMatched.IsDefined)
            {
                routeNotMatched.Value(url);
            }
        }