/// <summary> /// 从HttpRequest中构造一个参数值 /// </summary> /// <param name="p"></param> /// <param name="requst"></param> /// <returns></returns> public virtual object GetParameter(ParameterInfo p, HttpRequest requst) { // 参数的第一种取值方式:通过[FromBody]指定,反序列化请求流 FromBodyAttribute attr = p.GetMyAttribute <FromBodyAttribute>(); if (attr != null) { return(FromBodyDeserializeObject(p, requst)); } // 参数的第二种取值方式:通过[FromRequest]指定,从HttpRequest中获取某个属性值 FromRequestAttribute a2 = p.GetMyAttribute <FromRequestAttribute>(); if (a2 != null) { return(FromRequestPropertyGetValue(p, requst)); } // 参数的第三种取值方式:根据参数名,从各种数据集合中获取(Route, QueryString, Form, Headers) string value = requst[p.Name]; if (value != null) { // 非序列化的参数,允许可空类型 return(_stringConverter.Instance.ToObject(value, p.ParameterType.GetRealType())); } // 查找失败 return(null); }
public ApiServiceCallParameter(ApiServiceCall call, ParameterInfo info) { this.ServiceCall = call; this.Parameter = info; this.FromBody = info.GetCustomAttribute <FromBodyAttribute>(); this.FromUri = info.GetCustomAttribute <FromUriAttribute>(); String route = call.Route.Template ?? String.Empty; if (FromUri != null) { if (!route.Contains($"{{{Parameter.Name}}}")) { FromQueryString = FromUri; FromUri = null; } } else if (FromBody == null) { if (route.Contains(Parameter.Name)) { FromUri = new FromUriAttribute(); } else { FromBody = new FromBodyAttribute(); } } }
public async Task <IActionResult> GetSpotifyUser(FromBodyAttribute authCode, string code) { var authToken = GetAuthToken(code); var userResponse = await SpotifyUser.GetCurrentUserProfile(authToken); return(Ok(userResponse)); }
public async Task <IActionResult> GetSpotifyUser(FromBodyAttribute authCode, string code) { var authToken = HttpHelper.Post("https://accounts.spotify.com/api/token", code); var userResponse = await SpotifyUser.GetCurrentUserProfile(authToken); await _dashboardHub.Clients.All.InvokeAsync("TestSend", "Hello From The Hub Server!!"); return(Ok(userResponse)); }
private static ParameterSourceAttribute GetDefaultParameterSource(ParameterInfo parameter) { if ((typeof(Guid) == parameter.ParameterType) || (typeof(DateTime) == parameter.ParameterType) || ((parameter.ParameterType.IsIdentity()) && (PopularIdentifierPropertyNames.Contains(parameter.Name, StringComparer.OrdinalIgnoreCase)))) { return(FromUrlAttribute.For(parameter)); } if ((!parameter.ParameterType.IsValueType) && (typeof(string) != parameter.ParameterType) && (!((System.TypeExtensions.IsEnumerable(parameter.ParameterType)) && (parameter.ParameterType.GetItemType().IsNumber())))) { return(FromBodyAttribute.For(parameter)); } return(FromQueryStringAttribute.For(parameter)); }
private void Process_MethodParams(MethodInfo mInfo, ref ApiMethodObj m) { //m.Attributes = attribs.Select(a => a.GetType().Name.Replace("Attribute", "")).ToList(); var allParams = mInfo.GetParameters(); if (allParams.Length == 1) { var p = GenerateApiMethodParamObj(allParams.First()); FromBodyAttribute fromBodyAttr = (FromBodyAttribute)Attribute.GetCustomAttribute(allParams.First(), typeof(FromBodyAttribute)); //if it is exactly one param && it has the attribute or it is complex type param then by default it is FromBody if (fromBodyAttr != null || !IsSimpleType(allParams.First().ParameterType)) { p.IsFromBody = true; } m.ParameterArray.Add(p); } else { //only one FromBody will receive the body params even if the attribute is put for multiple params. //src: https://stackoverflow.com/questions/24874490/pass-multiple-complex-objects-to-a-post-put-web-api-method bool isFromBodyAlreadySet = false; foreach (var pInfo in mInfo.GetParameters().OrderBy(p => p.Position)) { var p = GenerateApiMethodParamObj(pInfo); FromBodyAttribute fromBodyAttr = (FromBodyAttribute)Attribute.GetCustomAttribute(pInfo, typeof(FromBodyAttribute)); if (!isFromBodyAlreadySet && fromBodyAttr != null) { p.IsFromBody = true; } m.ParameterArray.Add(p); } } }
private static OperationInfo <Verb> CreateOperation(MethodInfo method, Verb verb) { string queryString = String.Empty; string uriTemplate = null; IList <ArgumentInfo> arguments = new List <ArgumentInfo>(); foreach (var parameter in method.GetParameters()) { if (parameter.IsOut) { continue; } string parameterTemplate = null; ParameterSourceAttribute source = null; if (parameter.ParameterType == typeof(Guid)) { source = FromUrlAttribute.For(parameter); uriTemplate += (parameterTemplate = "/" + parameter.Name + "/{?value}"); } else if (parameter.ParameterType.IsValueType) { source = FromQueryStringAttribute.For(parameter); queryString += (parameterTemplate = "&" + parameter.Name + "={?value}"); } else if (!parameter.ParameterType.IsValueType) { source = FromBodyAttribute.For(parameter); } arguments.Add(new ArgumentInfo(parameter, source, parameterTemplate, (parameterTemplate != null ? parameter.Name : null))); } if (queryString.Length > 0) { uriTemplate += "?" + queryString.Substring(1); } return(new OperationInfo <Verb>(method, (HttpUrl)UrlParser.Parse("/"), uriTemplate, new Regex(".*"), verb, arguments.ToArray()).WithSecurityDetailsFrom(method)); }
private object[] GetMultiObjectsFormString(string input, ActionDescription action, HttpContext context) { JObject jsonObj = JObject.Parse(input); DefaultJsonSerializer jsonnet = new DefaultJsonSerializer(); JsonSerializerSettings settings = jsonnet.GetJsonSerializerSettings(false); Newtonsoft.Json.JsonSerializer jsonSerializer = Newtonsoft.Json.JsonSerializer.CreateDefault(settings); object[] parameters = new object[action.Parameters.Length]; for (int i = 0; i < parameters.Length; i++) { FromBodyAttribute bodyAttr = action.Parameters[i].GetMyAttribute <FromBodyAttribute>(false); if (bodyAttr != null) { // 当前参数需要从整体请求体中反序列化得到参数值 parameters[i] = GetObjectFromString(input, action); } else { //尝试从JSON中获取一个片段,用这个片段来构造参数值 JToken childObj = jsonObj.GetValue(action.Parameters[i].Name, StringComparison.OrdinalIgnoreCase); if (childObj != null) { Type pType = action.Parameters[i].ParameterType; parameters[i] = childObj.ToObject(pType, jsonSerializer); } else { // 再次尝试从HTTP上下文中获取 parameters[i] = GetParameterFromHttp(context, action.Parameters[i]); } } } return(parameters); }
// 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)); }
private static ParameterSourceAttribute GetParameterTarget(this ParameterInfo parameter) { var explicitSetting = parameter.GetCustomAttribute <ParameterSourceAttribute>(true); if (explicitSetting != null) { return(explicitSetting); } if ((typeof(Guid) == parameter.ParameterType) || (typeof(DateTime) == parameter.ParameterType) || ((IsIdentity(parameter.ParameterType)) && (PopularIdentifierPropertyNames.Contains(parameter.Name, StringComparer.OrdinalIgnoreCase)))) { return(FromUrlAttribute.For(parameter)); } if ((!parameter.ParameterType.IsValueType) && (typeof(string) != parameter.ParameterType) && (!((System.TypeExtensions.IsEnumerable(parameter.ParameterType)) && (IsNumber(parameter.ParameterType.GetItemType()))))) { return(FromBodyAttribute.For(parameter)); } return(FromQueryStringAttribute.For(parameter)); }
// 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.IsSimpleUnderlyingType(type) || TypeHelper.HasStringConverter(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); }
Service ProcessService(Type type) { bool enabled = true; Service service = new Service() { Name = type.Name.Replace("Api", "").Replace("Controller", ""), }; DiscoveryAttribute discoveryAttr = type.GetCustomAttribute <DiscoveryAttribute>(true); if (discoveryAttr != null) { service.DiscoveryName = discoveryAttr.DiscoveryName; service.Dependency = discoveryAttr.Dependency; enabled = discoveryAttr.Enabled; } if (enabled) { string hostAddress = _HostAddress + (_HostAddress.EndsWith("/") ? "" : "/"); string routePrefix = string.Empty; RouteAttribute routePrefixAttr = type.GetCustomAttribute <RouteAttribute>(true); if (routePrefixAttr != null) { routePrefix = routePrefixAttr.Template + (routePrefixAttr.Template.EndsWith("/") ? "" : "/"); } List <Operation> operations = new List <Operation>(); MethodInfo[] methods = type.GetMethods(); foreach (MethodInfo methodInfo in methods) { string method = string.Empty; string route = string.Empty; string discoveryName = string.Empty; string dependency = string.Empty; // public method only declared in this class if (methodInfo.IsPublic && methodInfo.DeclaringType.FullName == type.FullName) { object[] methodAttrs = methodInfo.GetCustomAttributes(false); foreach (object methodAttr in methodAttrs) { Type methodAttrType = methodAttr.GetType(); Type[] httpAttrInterfaces = methodAttrType.GetInterfaces(); foreach (Type interfaceType in httpAttrInterfaces) { if (interfaceType.Equals(typeof(IActionHttpMethodProvider))) { // found HTTP attribute method = methodAttrType.Name.Replace("Http", "").Replace("Attribute", "").ToUpper(); route = ((HttpMethodAttribute)methodAttr).Template; break; } } if (methodAttrType.Equals(typeof(RouteAttribute))) { // process route and method arguments - Route attribute template overrides very attribute template RouteAttribute routeAttr = methodAttr as RouteAttribute; if (routeAttr != null) { route = routeAttr.Template; } } //if (methodInfo.Name == "Calc3") // System.Diagnostics.Debugger.Break(); if (!string.IsNullOrWhiteSpace(route)) { ParameterInfo[] arguments = methodInfo.GetParameters(); if (arguments != null) { List <ParameterInfo> parameters = new List <ParameterInfo>(); ParameterInfo fromBodyParameter = null; foreach (ParameterInfo parameterInfo in arguments) { if (!parameterInfo.ParameterType.Equals(typeof(HttpRequestMessage))) { FromBodyAttribute fromBodyAttr = parameterInfo.GetCustomAttribute <FromBodyAttribute>(false); FromFormAttribute fromFormAttr = parameterInfo.GetCustomAttribute <FromFormAttribute>(false); if (fromBodyAttr == null && fromFormAttr == null) { // ensure parameter name is not already in the route if (route.IndexOf("{" + parameterInfo.Name + "}") == -1) { // parameter is in method signature but not in route parameters.Add(parameterInfo); } } else { fromBodyParameter = parameterInfo; } } } if (parameters.Count > 0) { int index = 0; foreach (ParameterInfo parameterInfo in parameters) { route += (index == 0 ? "?" : "&") + parameterInfo.Name + "={" + parameterInfo.Name + "}"; index++; } } } } if (methodAttrType.Equals(typeof(DiscoveryAttribute))) { DiscoveryAttribute opDiscAttr = methodAttr as DiscoveryAttribute; if (opDiscAttr != null) { discoveryName = opDiscAttr.DiscoveryName; dependency = opDiscAttr.Dependency; } } } if (method == string.Empty) { method = "GET"; } if (route.StartsWith("~/")) { route = route.Substring(2); } else { route = routePrefix + route; } Operation operation = new Operation() { Name = methodInfo.Name, Method = method, Route = route, DiscoveryName = discoveryName, Dependency = dependency }; // if no discovery nane found, make one out of route if (string.IsNullOrWhiteSpace(operation.DiscoveryName) && !string.IsNullOrWhiteSpace(operation.Route)) { Uri uri = new Uri(this._HostAddress + operation.Route); string localPath = uri.LocalPath; if (localPath.IndexOf("?") > -1) { operation.DiscoveryName = localPath.Substring(1, uri.LocalPath.IndexOf("?") - 1); } else if (localPath.IndexOf("{") > -1) { operation.DiscoveryName = localPath.Substring(1, uri.LocalPath.IndexOf("{") - 1); } else { operation.DiscoveryName = localPath; } if (operation.DiscoveryName.StartsWith("/")) { operation.DiscoveryName = operation.DiscoveryName.Substring(1); } if (operation.DiscoveryName.EndsWith("/")) { operation.DiscoveryName = operation.DiscoveryName.Substring(0, operation.DiscoveryName.Length - 1); } } operations.Add(operation); } } service.Operations = operations; } else { service = null; } return(service); }
private object[] GetMultiObjectsFormRequest(HttpContext context, ActionDescription action) { HttpRequest request = context.Request; string xml = request.ReadInputStream(); XmlDocument doc = new XmlDocument(); doc.LoadXml(xml); XmlNode root = doc.LastChild; //if( root.ChildNodes.Count != action.Parameters.Length ) // throw new ArgumentException("客户端提交的数据项与服务端的参数项的数量不匹配。"); object[] parameters = new object[action.Parameters.Length]; LazyObject <ModelBuilder> builder = new LazyObject <ModelBuilder>(); for (int i = 0; i < parameters.Length; i++) { FromBodyAttribute bodyAttr = action.Parameters[i].GetMyAttribute <FromBodyAttribute>(false); if (bodyAttr != null) { // 当前参数需要从整体请求体中反序列化得到参数值 parameters[i] = GetObjectFromRequest(context, action); } else { string name = action.Parameters[i].Name; XmlNode node = (from n in root.ChildNodes.Cast <XmlNode>() where string.Compare(n.Name, name, StringComparison.OrdinalIgnoreCase) == 0 select n).FirstOrDefault(); if (node != null) { try { object parameter = null; Type destType = action.Parameters[i].ParameterType.GetRealType(); if (destType.IsSupportableType()) // 如果是简单类型,就不需要反序列化 { parameter = builder.Instance.StringToObject(node.InnerText, destType); } else { // 复杂类型的参数,就使用反序列化 parameter = XmlDeserialize(node.OuterXml, destType, request.ContentEncoding); } parameters[i] = parameter; } catch (Exception ex) { throw new InvalidCastException("数据转换失败,当前参数名:" + name, ex); } } else { // 再次尝试从HTTP上下文中获取 parameters[i] = GetParameterFromHttp(context, action.Parameters[i]); } } } return(parameters); }
public void Setup() { Mock <IDefaultValueRelationSelector> defaultSourceSelector = new Mock <IDefaultValueRelationSelector>(MockBehavior.Strict); defaultSourceSelector.Setup(instance => instance.ProvideDefault(It.IsAny <ParameterInfo>(), It.IsAny <Verb>())) .Returns <ParameterInfo, Verb>((parameter, verb) => (parameter.ParameterType == typeof(int) ? (ParameterSourceAttribute)FromUrlAttribute.For(parameter) : FromBodyAttribute.For(parameter))); defaultSourceSelector.Setup(instance => instance.ProvideDefault(It.IsAny <ParameterInfo>())) .Returns <ParameterInfo>(parameter => new ToBodyAttribute()); _builder = new ControllerDescriptionBuilder <CrudController>(defaultSourceSelector.Object); }
public IHttpActionResult createQuiz(FromBodyAttribute fromBody) { }