System.Web.Routing.PatternParser.BuildUrl C# (CSharp) Method

BuildUrl() public method

public BuildUrl ( Route route, System.Web.Routing.RequestContext requestContext, RouteValueDictionary userValues, string &value ) : bool
route Route
requestContext System.Web.Routing.RequestContext
userValues RouteValueDictionary
value string
return bool
		public bool BuildUrl (Route route, RequestContext requestContext, RouteValueDictionary userValues, out string value)
		{
			value = null;
			if (requestContext == null)
				return false;

			RouteData routeData = requestContext.RouteData;
			RouteValueDictionary defaultValues = route != null ? route.Defaults : null;
			RouteValueDictionary ambientValues = routeData.Values;

			if (defaultValues != null && defaultValues.Count == 0)
				defaultValues = null;
			if (ambientValues != null && ambientValues.Count == 0)
				ambientValues = null;
			if (userValues != null && userValues.Count == 0)
				userValues = null;

			// Check URL parameters
			// It is allowed to take ambient values for required parameters if:
			//
			//   - there are no default values provided
			//   - the default values dictionary contains at least one required
			//     parameter value
			//
			bool canTakeFromAmbient;
			if (defaultValues == null)
				canTakeFromAmbient = true;
			else {
				canTakeFromAmbient = false;
				foreach (KeyValuePair <string, bool> de in parameterNames) {
					if (defaultValues.ContainsKey (de.Key)) {
						canTakeFromAmbient = true;
						break;
					}
				}
			}
			
			bool allMustBeInUserValues = false;
			foreach (KeyValuePair <string, bool> de in parameterNames) {
				string parameterName = de.Key;
				// Is the parameter required?
				if (defaultValues == null || !defaultValues.ContainsKey (parameterName)) {
					// Yes, it is required (no value in defaults)
					// Has the user provided value for it?
					if (userValues == null || !userValues.ContainsKey (parameterName)) {
						if (allMustBeInUserValues)
							return false; // partial override => no match
						
						if (!canTakeFromAmbient || ambientValues == null || !ambientValues.ContainsKey (parameterName))
							return false; // no value provided => no match
					} else if (canTakeFromAmbient)
						allMustBeInUserValues = true;
				}
			}

			// Check for non-url parameters
			if (defaultValues != null) {
				foreach (var de in defaultValues) {
					string parameterName = de.Key;
					
					if (parameterNames.ContainsKey (parameterName))
						continue;

					object parameterValue = null;
					// Has the user specified value for this parameter and, if
					// yes, is it the same as the one in defaults?
					if (userValues != null && userValues.TryGetValue (parameterName, out parameterValue)) {
						object defaultValue = de.Value;
						if (defaultValue is string && parameterValue is string) {
							if (String.Compare ((string)defaultValue, (string)parameterValue, StringComparison.Ordinal) != 0)
								return false; // different value => no match
						} else if (defaultValue != parameterValue)
							return false; // different value => no match
					}
				}
			}

			// Check the constraints
			RouteValueDictionary constraints = route != null ? route.Constraints : null;
			if (constraints != null && constraints.Count > 0) {
				HttpContextBase context = requestContext.HttpContext;
				bool invalidConstraint;
				
				foreach (var de in constraints) {
					if (!Route.ProcessConstraintInternal (context, route, de.Value, de.Key, userValues, RouteDirection.UrlGeneration, out invalidConstraint) ||
					    invalidConstraint)
						return false; // constraint not met => no match
				}
			}

			// We're a match, generate the URL
			var ret = new StringBuilder ();
			bool canTrim = true;
			
			// Going in reverse order, so that we can trim without much ado
			int tokensCount = tokens.Length - 1;
			for (int i = tokensCount; i >= 0; i--) {
				PatternToken token = tokens [i];
				if (token == null) {
					if (i < tokensCount && ret.Length > 0 && ret [0] != '/')
						ret.Insert (0, '/');
					continue;
				}
				
				if (token.Type == PatternTokenType.Literal) {
					ret.Insert (0, token.Name);
					continue;
				}

				string parameterName = token.Name;
				object tokenValue;

#if SYSTEMCORE_DEP
				if (userValues.GetValue (parameterName, out tokenValue)) {
					if (!defaultValues.Has (parameterName, tokenValue)) {
						canTrim = false;
						if (tokenValue != null)
							ret.Insert (0, tokenValue.ToString ());
						continue;
					}

					if (!canTrim && tokenValue != null)
						ret.Insert (0, tokenValue.ToString ());
					continue;
				}

				if (defaultValues.GetValue (parameterName, out tokenValue)) {
					object ambientTokenValue;
					if (ambientValues.GetValue (parameterName, out ambientTokenValue))
						tokenValue = ambientTokenValue;
					
					if (!canTrim && tokenValue != null)
						ret.Insert (0, tokenValue.ToString ());
					continue;
				}

				canTrim = false;
				if (ambientValues.GetValue (parameterName, out tokenValue)) {
					if (tokenValue != null)
						ret.Insert (0, tokenValue.ToString ());
					continue;
				}
#endif
			}

			// All the values specified in userValues that aren't part of the original
			// URL, the constraints or defaults collections are treated as overflow
			// values - they are appended as query parameters to the URL
			if (userValues != null) {
				bool first = true;
				foreach (var de in userValues) {
					string parameterName = de.Key;

#if SYSTEMCORE_DEP
					if (parameterNames.ContainsKey (parameterName) || defaultValues.Has (parameterName) || constraints.Has (parameterName))
						continue;
#endif

					object parameterValue = de.Value;
					if (parameterValue == null)
						continue;

					var parameterValueAsString = parameterValue as string;
					if (parameterValueAsString != null && parameterValueAsString.Length == 0)
						continue;
					
					if (first) {
						ret.Append ('?');
						first = false;
					} else
						ret.Append ('&');

					
					ret.Append (Uri.EscapeDataString (parameterName));
					ret.Append ('=');
					if (parameterValue != null)
						ret.Append (Uri.EscapeDataString (de.Value.ToString ()));
				}
			}
			
			value = ret.ToString ();
			return true;
		}
	}

Usage Example

Example #1
0
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }
            if (url == null)
            {
                return(new VirtualPathData(this, String.Empty));
            }

            // null values is allowed.
            // if (values == null)
            //  values = requestContext.RouteData.Values;

            RouteValueDictionary usedValues;
            string resultUrl = url.BuildUrl(this, requestContext, values, Constraints, out usedValues);

            if (resultUrl == null)
            {
                return(null);
            }

            if (!ProcessConstraints(requestContext.HttpContext, usedValues, RouteDirection.UrlGeneration))
            {
                return(null);
            }

            var result = new VirtualPathData(this, resultUrl);

            RouteValueDictionary dataTokens = DataTokens;

            if (dataTokens != null)
            {
                foreach (var item in dataTokens)
                {
                    result.DataTokens[item.Key] = item.Value;
                }
            }

            return(result);
        }
All Usage Examples Of System.Web.Routing.PatternParser::BuildUrl