private static Type GetLetterHandlerTypeFromDirectRoute(AddressData addressData) { Contract.Assert(addressData != null); var matchingAddressDatas = addressData.GetDirectAddressMatches(); List <Type> letterHandlerTypes = new List <Type>(); foreach (var directAddressData in matchingAddressDatas) { if (directAddressData != null) { Type letterHandlerType = directAddressData.GetTargetLetterHandlerType(); if (letterHandlerType == null) { // We don't expect this to happen, but it could happen if some code messes with the // address data tokens and removes the key we're looking for. throw new InvalidOperationException("Missing Letter Handler Type"); } if (!letterHandlerTypes.Contains(letterHandlerType)) { letterHandlerTypes.Add(letterHandlerType); } } } // We only want to handle the case where all matched direct addresses refer to the same letter handler. // Handling the multiple-letter handlers case would put attribute routing down a totally different // path than traditional addressing. if (letterHandlerTypes.Count == 0) { return(null); } else if (letterHandlerTypes.Count == 1) { return(letterHandlerTypes[0]); } else { throw CreateDirectAddressAmbiguousLetterHandlerException(letterHandlerTypes); } }
/// <summary> /// Gets the ControllerDescriptor that matches this Address. /// </summary> public static LetterHandlerDescriptor GetTargetLetterHandlerDescriptor(this AddressData AddressData) { var actions = GetTargetActionDescriptors(AddressData); LetterHandlerDescriptor letterHandler = null; foreach (var action in actions) { if (letterHandler == null) { letterHandler = action.LetterHandlerDescriptor; } else if (letterHandler != action.LetterHandlerDescriptor) { // Don't provide a single controller descriptor if multiple controllers match. return(null); } } return(letterHandler); }
private static IEnumerable <AddressData> GetAddressDataValue(this AddressData AddressData, string key) { if (AddressData == null) { throw new Exception(); } if (key == null) { throw new Exception(); } IEnumerable <AddressData> value; if (AddressData.Values.TryGetValue(key, out value)) { return(value); } else { return(default(IEnumerable <AddressData>)); } }
protected internal virtual Type GetLetterHandlerType(RequestContext requestContext, string letterHandlerName) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } if (String.IsNullOrEmpty(letterHandlerName) && (requestContext.AddressData == null || !requestContext.AddressData.HasDirectAddressMatch())) { throw new ArgumentException("null or empty", "letterHandlerName"); } AddressData addressData = requestContext.AddressData; if (addressData != null && addressData.HasDirectAddressMatch()) { return(GetLetterHandlerTypeFromDirectRoute(addressData)); } // first search in the current route's namespace collection object routeNamespacesObj; Type match; if (addressData != null && addressData.DataTokens.TryGetValue(AddressDataTokenKeys.Namespaces, out routeNamespacesObj)) { IEnumerable <string> routeNamespaces = routeNamespacesObj as IEnumerable <string>; if (routeNamespaces != null && routeNamespaces.Any()) { HashSet <string> namespaceHash = new HashSet <string>(routeNamespaces, StringComparer.OrdinalIgnoreCase); match = GetLetterHandlerTypeWithinNamespaces(addressData.Address, letterHandlerName, namespaceHash); // the UseNamespaceFallback key might not exist, in which case its value is implicitly "true" if (match != null || false.Equals(addressData.DataTokens[AddressDataTokenKeys.UseNamespaceFallback])) { // got a match or the route requested we stop looking return(match); } } } // then search in the application's default namespace collection Address route = addressData == null ? null : addressData.Address; if (LetterHandlerBuilder.DefaultNamespaces.Count > 0) { HashSet <string> namespaceDefaults = new HashSet <string>(LetterHandlerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase); match = GetLetterHandlerTypeWithinNamespaces(route, letterHandlerName, namespaceDefaults); if (match != null) { return(match); } } // if all else fails, search every namespace return(GetLetterHandlerTypeWithinNamespaces(route, letterHandlerName, null /* namespaces */)); // If you are reading this then you probably want to do something different. }
public RequestContext(HttpContextBase httpContext, AddressData addressData) { HttpContext = httpContext as HttpContext; AddressData = addressData; }
/// <summary> /// Gets a value indicating whether or not the Address is a direct Address to an action. /// </summary> public static bool GetTargetIsAction(this AddressData AddressData) { return(GetAddressDataTokenValue <bool>(AddressData, AddressDataTokenKeys.TargetIsAction)); }
/// <summary> /// Gets the order or this Address. /// </summary> public static int GetOrder(this AddressData AddressData) { return(GetAddressDataTokenValue <int>(AddressData, AddressDataTokenKeys.Order)); }
public static IEnumerable <AddressData> GetDirectAddressMatches(this AddressData AddressData) { return(GetAddressDataValue(AddressData, AddressDataTokenKeys.DirectAddressMatches) ?? Enumerable.Empty <AddressData>()); }
/// <summary> /// Gets the precedence or this Address. /// </summary> public static decimal GetPrecedence(this AddressData AddressData) { return(GetAddressDataTokenValue <decimal>(AddressData, AddressDataTokenKeys.Precedence)); }
/// <summary> /// Gets the target actions that can be matched if this Address is matched. /// </summary> public static ActionDescriptor[] GetTargetActionDescriptors(this AddressData AddressData) { return(GetAddressDataTokenValue <ActionDescriptor[]>(AddressData, AddressDataTokenKeys.Actions)); }
public static Type GetTargetLetterHandlerType(this AddressData AddressData) { LetterHandlerDescriptor letterHandlerDescriptor = AddressData.GetTargetLetterHandlerDescriptor(); return(letterHandlerDescriptor == null ? null : letterHandlerDescriptor.LetterHandlerType); }