Пример #1
0
        private static bool TryExpandUriParameters(IHttpRoute route, HttpParsedRoute parsedRoute, ICollection <ApiParameterDescription> parameterDescriptions, out string expandedRouteTemplate)
        {
            Dictionary <string, object> parameterValuesForRoute = new Dictionary <string, object>();

            foreach (ApiParameterDescription parameterDescriptor in parameterDescriptions)
            {
                if (parameterDescriptor.Source == ApiParameterSource.FromUri)
                {
                    if (parameterDescriptor.ParameterDescriptor == null ||
                        (parameterDescriptor.ParameterDescriptor != null &&
                         TypeHelper.CanConvertFromString(parameterDescriptor.ParameterDescriptor.ParameterType)))
                    {
                        parameterValuesForRoute.Add(parameterDescriptor.Name, "{" + parameterDescriptor.Name + "}");
                    }
                }
            }

            BoundRouteTemplate boundRouteTemplate = parsedRoute.Bind(null, parameterValuesForRoute, new HttpRouteValueDictionary(route.Defaults), new HttpRouteValueDictionary(route.Constraints));

            if (boundRouteTemplate == null)
            {
                expandedRouteTemplate = null;
                return(false);
            }

            expandedRouteTemplate = Uri.UnescapeDataString(boundRouteTemplate.BoundTemplate);
            return(true);
        }
Пример #2
0
            public ActionSelectorCacheItem(HttpControllerDescriptor controllerDescriptor)
            {
                Contract.Assert(controllerDescriptor != null);

                // Initialize the cache entirely in the ctor on a single thread.
                _controllerDescriptor = controllerDescriptor;

                MethodInfo[] allMethods   = _controllerDescriptor.ControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
                MethodInfo[] validMethods = Array.FindAll(allMethods, IsValidActionMethod);

                _combinedCandidateActions = new CandidateAction[validMethods.Length];
                for (int i = 0; i < validMethods.Length; i++)
                {
                    MethodInfo method = validMethods[i];
                    ReflectedHttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(_controllerDescriptor, method);
                    _combinedCandidateActions[i] = new CandidateAction
                    {
                        ActionDescriptor = actionDescriptor
                    };
                    HttpActionBinding actionBinding = actionDescriptor.ActionBinding;

                    // Building an action parameter name mapping to compare against the URI parameters coming from the request. Here we only take into account required parameters that are simple types and come from URI.
                    _actionParameterNames.Add(
                        actionDescriptor,
                        actionBinding.ParameterBindings
                        .Where(binding => !binding.Descriptor.IsOptional && TypeHelper.CanConvertFromString(binding.Descriptor.ParameterType) && binding.WillReadUri())
                        .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName).ToArray());
                }

                _combinedActionNameMapping =
                    _combinedCandidateActions
                    .Select(c => c.ActionDescriptor)
                    .ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);
            }
Пример #3
0
 private static bool ShouldEmitPrefixes(ICollection <ApiParameterDescription> parameterDescriptions)
 {
     // Determine if there are two or more complex objects from the Uri so TryExpandUriParameters needs to emit prefixes.
     return(parameterDescriptions.Count(parameter =>
                                        parameter.Source == ApiParameterSource.FromUri &&
                                        parameter.ParameterDescriptor != null &&
                                        !TypeHelper.CanConvertFromString(parameter.ParameterDescriptor.ParameterType) &&
                                        parameter.CanConvertPropertiesFromString()) > 1);
 }
Пример #4
0
        // Set as internal for the unit test.
        internal static bool TryExpandUriParameters(IHttpRoute route, HttpParsedRoute parsedRoute, ICollection <ApiParameterDescription> parameterDescriptions, out string expandedRouteTemplate)
        {
            Dictionary <string, object> parameterValuesForRoute = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);
            bool   emitPrefixes = ShouldEmitPrefixes(parameterDescriptions);
            string prefix       = String.Empty;

            foreach (ApiParameterDescription parameterDescriptor in parameterDescriptions)
            {
                if (parameterDescriptor.Source == ApiParameterSource.FromUri)
                {
                    if (parameterDescriptor.ParameterDescriptor == null ||
                        (parameterDescriptor.ParameterDescriptor != null &&
                         TypeHelper.CanConvertFromString(parameterDescriptor.ParameterDescriptor.ParameterType)))
                    {
                        if (!parameterValuesForRoute.ContainsKey(parameterDescriptor.Name))
                        {
                            parameterValuesForRoute.Add(parameterDescriptor.Name, "{" + parameterDescriptor.Name + "}");
                        }
                    }
                    else if (parameterDescriptor.ParameterDescriptor != null &&
                             parameterDescriptor.CanConvertPropertiesFromString())
                    {
                        if (emitPrefixes)
                        {
                            prefix = parameterDescriptor.Name + ".";
                        }

                        // Inserting the individual properties of the object in the query string
                        // as all the complex object can not be converted from string, but all its
                        // individual properties can.
                        foreach (PropertyInfo property in parameterDescriptor.GetBindableProperties())
                        {
                            string queryParameterName = prefix + property.Name;
                            if (!parameterValuesForRoute.ContainsKey(queryParameterName))
                            {
                                parameterValuesForRoute.Add(queryParameterName, "{" + queryParameterName + "}");
                            }
                        }
                    }
                }
            }

            BoundRouteTemplate boundRouteTemplate = parsedRoute.Bind(null, parameterValuesForRoute, new HttpRouteValueDictionary(route.Defaults), new HttpRouteValueDictionary(route.Constraints));

            if (boundRouteTemplate == null)
            {
                expandedRouteTemplate = null;
                return(false);
            }

            expandedRouteTemplate = Uri.UnescapeDataString(boundRouteTemplate.BoundTemplate);
            return(true);
        }
Пример #5
0
        private object ExecuteBindingCore(HttpRequest request)
        {
            Type   type  = ParameterDescriptor.ParameterType;
            string value = request[ParameterDescriptor.Name];

            if (string.IsNullOrWhiteSpace(value))
            {
                return(ParameterDescriptor.DefaultValue);
            }

            if (TypeHelper.CanConvertFromString(type))
            {
                TypeConverter converter = TypeDescriptor.GetConverter(type);
                return(converter.ConvertFromString(value));
            }

            return(ParameterDescriptor.DefaultValue);
        }
        private static ParameterBinding GetParameterBinding(ParameterDescriptor descriptor)
        {
            ParameterBindingAttribute attribute = descriptor.ParameterBindingAttribute;

            if (attribute != null)
            {
                return(attribute.GetBinding(descriptor));
            }

            /*
             *  TODO: Configure 自定义配置项绑定器
             */

            Type type = descriptor.ParameterType;

            if (TypeHelper.CanConvertFromString(type))
            {
                return(descriptor.BindWithAttribute(new FromUriAttribute()));
            }

            return(descriptor.BindWithAttribute(new FromBodyAttribute()));
        }
        // Determine how a single parameter will get bound.
        // This is all sync. We don't need to actually read the body just to determine that we'll bind to the body.
        protected virtual HttpParameterBinding GetParameterBinding(
            HttpParameterDescriptor parameter
            )
        {
            // Attribute has the highest precedence
            // Presence of a model binder attribute overrides.
            ParameterBindingAttribute attr = parameter.ParameterBinderAttribute;

            if (attr != null)
            {
                return(attr.GetBinding(parameter));
            }

            // No attribute, so lookup in global map.
            ParameterBindingRulesCollection pb = parameter.Configuration.ParameterBindingRules;

            if (pb != null)
            {
                HttpParameterBinding binding = pb.LookupBinding(parameter);
                if (binding != null)
                {
                    return(binding);
                }
            }

            // Not explicitly specified in global map or attribute.
            // Use a default policy to determine it. These are catch-all policies.
            Type type = parameter.ParameterType;

            if (TypeHelper.CanConvertFromString(type))
            {
                // For simple types, the default is to look in URI. Exactly as if the parameter had a [FromUri] attribute.
                return(parameter.BindWithAttribute(new FromUriAttribute()));
            }

            // Fallback. Must be a complex type. Default is to look in body. Exactly as if this type had a [FromBody] attribute.
            attr = new FromBodyAttribute();
            return(attr.GetBinding(parameter));
        }
Пример #8
0
        // Set as internal for the unit test.
        internal static bool TryExpandUriParameters(IHttpRoute route, HttpParsedRoute parsedRoute, ICollection <ApiParameterDescription> parameterDescriptions, out string expandedRouteTemplate)
        {
            Dictionary <string, object> parameterValuesForRoute = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);
            bool   emitPrefixes = ShouldEmitPrefixes(parameterDescriptions);
            string prefix       = String.Empty;

            foreach (ApiParameterDescription parameterDescription in parameterDescriptions)
            {
                if (parameterDescription.Source == ApiParameterSource.FromUri)
                {
                    if (parameterDescription.ParameterDescriptor == null)
                    {
                        // Undeclared route parameter handling generates query string like
                        // "?name={name}"
                        AddPlaceholder(parameterValuesForRoute, parameterDescription.Name);
                    }
                    else if (TypeHelper.CanConvertFromString(parameterDescription.ParameterDescriptor.ParameterType))
                    {
                        // Simple type generates query string like
                        // "?name={name}"
                        AddPlaceholder(parameterValuesForRoute, parameterDescription.Name);
                    }
                    else if (IsBindableCollection(parameterDescription.ParameterDescriptor.ParameterType))
                    {
                        string parameterName = parameterDescription.ParameterDescriptor.ParameterName;
                        Type   innerType     =
                            GetCollectionElementType(parameterDescription.ParameterDescriptor.ParameterType);
                        PropertyInfo[] innerTypeProperties =
                            ApiParameterDescription.GetBindableProperties(innerType).ToArray();
                        if (innerTypeProperties.Any())
                        {
                            // Complex array and collection generate query string like
                            // "?name[0].foo={name[0].foo}&name[0].bar={name[0].bar}
                            //  &name[1].foo={name[1].foo}&name[1].bar={name[1].bar}"
                            AddPlaceholderForProperties(parameterValuesForRoute,
                                                        innerTypeProperties,
                                                        parameterName + "[0].");
                            AddPlaceholderForProperties(parameterValuesForRoute,
                                                        innerTypeProperties,
                                                        parameterName + "[1].");
                        }
                        else
                        {
                            // Simple array and collection generate query string like
                            // "?name[0]={name[0]}&name[1]={name[1]}".
                            AddPlaceholder(parameterValuesForRoute, parameterName + "[0]");
                            AddPlaceholder(parameterValuesForRoute, parameterName + "[1]");
                        }
                    }
                    else if (IsBindableKeyValuePair(parameterDescription.ParameterDescriptor.ParameterType))
                    {
                        // KeyValuePair generates query string like
                        // "?key={key}&value={value}"
                        AddPlaceholder(parameterValuesForRoute, "key");
                        AddPlaceholder(parameterValuesForRoute, "value");
                    }
                    else if (IsBindableDictionry(parameterDescription.ParameterDescriptor.ParameterType))
                    {
                        // Dictionary generates query string like
                        // "?dict[0].key={dict[0].key}&dict[0].value={dict[0].value}
                        //  &dict[1].key={dict[1].key}&dict[1].value={dict[1].value}"
                        string parameterName = parameterDescription.ParameterDescriptor.ParameterName;
                        AddPlaceholder(parameterValuesForRoute, parameterName + "[0].key");
                        AddPlaceholder(parameterValuesForRoute, parameterName + "[0].value");
                        AddPlaceholder(parameterValuesForRoute, parameterName + "[1].key");
                        AddPlaceholder(parameterValuesForRoute, parameterName + "[1].value");
                    }
                    else if (parameterDescription.CanConvertPropertiesFromString())
                    {
                        if (emitPrefixes)
                        {
                            prefix = parameterDescription.Name + ".";
                        }

                        // Inserting the individual properties of the object in the query string
                        // as all the complex object can not be converted from string, but all its
                        // individual properties can.
                        AddPlaceholderForProperties(parameterValuesForRoute,
                                                    parameterDescription.GetBindableProperties(),
                                                    prefix);
                    }
                }
            }

            BoundRouteTemplate boundRouteTemplate = parsedRoute.Bind(null, parameterValuesForRoute, new HttpRouteValueDictionary(route.Defaults), new HttpRouteValueDictionary(route.Constraints));

            if (boundRouteTemplate == null)
            {
                expandedRouteTemplate = null;
                return(false);
            }

            expandedRouteTemplate = Uri.UnescapeDataString(boundRouteTemplate.BoundTemplate);
            return(true);
        }
            public ActionSelectorCacheItem(HttpControllerDescriptor controllerDescriptor)
            {
                Contract.Assert(controllerDescriptor != null);

                // Initialize the cache entirely in the ctor on a single thread.
                _controllerDescriptor = controllerDescriptor;

                MethodInfo[] allMethods   = _controllerDescriptor.ControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
                MethodInfo[] validMethods = Array.FindAll(allMethods, IsValidActionMethod);

                _combinedCandidateActions = new CandidateAction[validMethods.Length];
                for (int i = 0; i < validMethods.Length; i++)
                {
                    MethodInfo method = validMethods[i];
                    ReflectedHttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(_controllerDescriptor, method);
                    _combinedCandidateActions[i] = new CandidateAction
                    {
                        ActionDescriptor = actionDescriptor
                    };
                    HttpActionBinding actionBinding = actionDescriptor.ActionBinding;

                    // Building an action parameter name mapping to compare against the URI parameters coming from the request. Here we only take into account required parameters that are simple types and come from URI.
                    _actionParameterNames.Add(
                        actionDescriptor,
                        actionBinding.ParameterBindings
                        .Where(binding => !binding.Descriptor.IsOptional && TypeHelper.CanConvertFromString(binding.Descriptor.ParameterType) && binding.WillReadUri())
                        .Select(binding => binding.Descriptor.Prefix ?? binding.Descriptor.ParameterName).ToArray());
                }

                if (controllerDescriptor.GetCustomAttributes <IHttpRouteInfoProvider>(inherit: false).Any())
                {
                    // The controller has an attribute route; no actions are accessible via standard routing.
                    _standardCandidateActions = new CandidateAction[0];
                }
                else
                {
                    // The controller does not have an attribute route; some actions may be accessible via standard
                    // routing.
                    List <CandidateAction> standardCandidateActions = new List <CandidateAction>();

                    for (int i = 0; i < _combinedCandidateActions.Length; i++)
                    {
                        CandidateAction candidate = _combinedCandidateActions[i];
                        // Allow standard routes access inherited actions or actions without Route attributes.
                        if (candidate.ActionDescriptor.MethodInfo.DeclaringType != controllerDescriptor.ControllerType ||
                            !candidate.ActionDescriptor.GetCustomAttributes <IHttpRouteInfoProvider>(inherit: false).Any())
                        {
                            standardCandidateActions.Add(candidate);
                        }
                    }

                    _standardCandidateActions = standardCandidateActions.ToArray();
                }

                _combinedActionNameMapping = _combinedCandidateActions.Select(c => c.ActionDescriptor).ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);
                _standardActionNameMapping = _standardCandidateActions.Select(c => c.ActionDescriptor).ToLookup(actionDesc => actionDesc.ActionName, StringComparer.OrdinalIgnoreCase);

                // Bucket the action descriptors by common verbs.
                int len = _cacheListVerbKinds.Length;

                _cacheListVerbs = new CandidateAction[len][];
                for (int i = 0; i < len; i++)
                {
                    _cacheListVerbs[i] = FindActionsForVerbWorker(_cacheListVerbKinds[i]);
                }
            }
Пример #10
0
 internal bool CanConvertPropertiesFromString()
 {
     return(GetBindableProperties().All(p => TypeHelper.CanConvertFromString(p.PropertyType)));
 }
 internal static bool CanConvertPropertiesFromString(this ApiParameterDescription description) =>
 description.GetBindableProperties().All(p => TypeHelper.CanConvertFromString(p.PropertyType));