private ResponseInfo HandleCrudRequest(IRequestMapping requestMapping, IList <object> resultingValues, object[] arguments, out bool success) { success = true; var methods = requestMapping.Target.GetType().DiscoverCrudMethods(); var method = methods.FirstOrDefault(entry => entry.Value == requestMapping.Operation.UnderlyingMethod); if (!Equals(method, default(KeyValuePair <Verb, MethodInfo>))) { switch (method.Key.ToString()) { case "": var type = requestMapping.Operation.UnderlyingMethod.ReturnType; var items = (resultingValues.Count > 1 ? (IEnumerable)resultingValues[1] : new[] { new object[0].MakeInstance(type, type.GetItemType()) }); var totalItems = (resultingValues.Count > 0 ? (int)resultingValues[0] : -1); return(MakeListResponse(requestMapping, items, arguments, totalItems)); case "GET": return(MakeGetResponse(requestMapping, (resultingValues.Count > 0 ? resultingValues[resultingValues.Count - 1] : null))); case "POST": return(MakePostResponse(requestMapping, (resultingValues.Count > 0 ? resultingValues[0] : null))); case "PUT": case "DELETE": return(MakeDeleteResponse(requestMapping)); } } success = false; return(null); }
private ResponseInfo MakeDeleteResponse(IRequestMapping requestMapping) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; result.Status = HttpStatusCode.NoContent; return(result); }
private ResponseInfo MakePostResponse(IRequestMapping requestMapping, object value) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; if (value == null) { result.Status = HttpStatusCode.BadRequest; return(result); } Type controllerType = null; var controllerDescriptor = (from controller in _controllerDescriptors.Value from operation in controller.Operations where operation.Equals(requestMapping.Operation) let type = controllerType = operation.UnderlyingMethod.ReflectedType select controller).FirstOrDefault(); if (controllerDescriptor == null) { throw new InvalidOperationException(String.Format("Cannot determine the default GET request handler for '{0}'.", requestMapping.Target.GetType())); } var getMethod = (from @interface in controllerType.GetInterfaces() where (@interface.IsGenericType) && (@interface.GetGenericTypeDefinition() == typeof(IReadController <,>)) from method in controllerType.GetInterfaceMap(@interface).TargetMethods join operation in controllerDescriptor.Operations on method equals operation.UnderlyingMethod select operation).First(); result.Headers.Add(new Header(Header.Location, getMethod.UrlTemplate.Replace("{" + getMethod.Arguments.First().VariableName + "}", value.ToString()))); result.Status = HttpStatusCode.Created; return(result); }
private ResponseInfo MakeListResponse(IRequestMapping requestMapping, IEnumerable resultingValues, object[] arguments, int totalItems = 0) { var status = HttpStatusCode.OK; ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; if ((arguments[1] != null) && (arguments[2] != null)) { int skip = (int)arguments[1]; int take = (int)arguments[2]; take = (take == 0 ? totalItems : Math.Min(take, resultingValues.Cast <object>().Count())); var contentRangeHeaderValue = String.Format("members {0}-{1}/{2}", skip, Math.Max(0, take - 1), totalItems); result.Headers.Add(new Header("Content-Range", contentRangeHeaderValue)); status = HttpStatusCode.PartialContent; } result = ObjectResponseInfo <object> .CreateInstance( result.Encoding, result.Request, requestMapping.Operation.UnderlyingMethod.ReturnType, resultingValues, _converterProvider, result.Headers); result.Status = status; return(result); }
private ResponseInfo MakeResponse(IRequestMapping requestMapping, IList <object> resultingValues) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; var bodyValues = new List <KeyValuePair <ResultInfo, object> >(); var headerValues = new List <KeyValuePair <ResultInfo, object> >(); requestMapping.Operation.Results.ForEach((resultValue, index) => (resultValue.Target is ToHeaderAttribute ? headerValues : bodyValues).Add(new KeyValuePair <ResultInfo, object>(resultValue, resultingValues[index]))); switch (bodyValues.Count) { case 0: break; case 1: var bodyValue = bodyValues[0]; result = ObjectResponseInfo <object> .CreateInstance(result.Encoding, result.Request, bodyValue.Value.GetType(), bodyValue.Value, _converterProvider, result.Headers); break; default: result = new MultiObjectResponseInfo(result.Encoding, result.Request, bodyValues.Select(item => item.Value), _converterProvider, result.Headers); break; } headerValues.ForEach(value => result.Headers.Add(new Header( ((ToHeaderAttribute)value.Key.Target).Name, String.Format(((ToHeaderAttribute)value.Key.Target).Format, _converterProvider.ConvertFrom(value.Value))))); return(result); }
public static bool IsHttpMethod(this IRequestMapping requestMapping, string httpMethod) { if (requestMapping == null) { return(false); } return(string.Equals(httpMethod, requestMapping.GetMethod(), StringComparison.OrdinalIgnoreCase)); }
public static bool IsSupportRequestContent(this IRequestMapping requestMapping) { return (requestMapping.IsHttpMethod(HttpMethod.Post) || requestMapping.IsHttpMethod(HttpMethod.Put) || requestMapping.IsHttpMethod(HttpMethod.Delete) || requestMapping.IsHttpMethod("PATCH") ); }
private async Task <object> ProcessModelTransformers(IRequestMapping requestMapping, RequestInfo requestInfo, object result, object[] arguments) { foreach (IModelTransformer modelTransformer in _modelTransformers) { result = await modelTransformer.Transform(requestMapping, requestInfo, result, arguments); } return(result); }
/// <inheritdoc /> public object[] BindArguments(IRequestInfo request, IRequestMapping requestMapping) { if (request == null) { throw new ArgumentNullException("request"); } if (!(request is RequestInfo)) { throw new InvalidOperationException(String.Format("Requests of type '{0}' are not supported.", request.GetType())); } return(BindArguments((RequestInfo)request, requestMapping)); }
private ResponseInfo MakeGetResponse(IRequestMapping requestMapping, object resultingValue) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; if (resultingValue == null) { result.Status = HttpStatusCode.NotFound; return(result); } result = ObjectResponseInfo <object> .CreateInstance(result.Encoding, result.Request, resultingValue.GetType(), resultingValue, _converterProvider, result.Headers); return(result); }
/// <inheritdoc /> public Task <object> Transform(IRequestMapping requestMapping, IRequestInfo request, object result, object[] arguments) { RequestInfo requestInfo; MethodInfo underlyingMethod; if (!CanOutputHypermedia((underlyingMethod = requestMapping.Operation.UnderlyingMethod).ReturnType, requestInfo = request as RequestInfo)) { return(Task.FromResult(result)); } int totalItems = ((IEnumerable)result).Cast <object>().Count(); int skip = 0; int take = 0; bool canOutputHypermedia = false; KeyValuePair <Verb, MethodInfo> method; if ((requestMapping.Target.GetType().GetImplementationOfAny(typeof(IController <>), typeof(IAsyncController <>)) != null) && (!Equals(method = requestMapping.Target.GetType().DiscoverCrudMethods().FirstOrDefault(entry => entry.Value == underlyingMethod), default(KeyValuePair <Verb, MethodInfo>)))) { switch (method.Key.ToString()) { case "": var parameters = underlyingMethod.GetParameters(); var resultingValues = arguments.Where((item, index) => parameters[index].IsOut).ToList(); totalItems = (resultingValues.Count > 0 ? (int)resultingValues[0] : -1); if ((arguments[1] != null) && (arguments[2] != null)) { skip = (int)arguments[1]; take = ((take = (int)arguments[2]) == 0 ? 0 : Math.Min(take, totalItems)); canOutputHypermedia = (requestMapping.ArgumentSources[1] == ArgumentValueSources.Bound) && (requestMapping.ArgumentSources[2] == ArgumentValueSources.Bound); } break; } } if (!canOutputHypermedia) { return(Task.FromResult(result)); } var namedGraphSelector = _namedGraphSelectorFactory.NamedGraphSelector; ILocallyControlledNamedGraphSelector locallyControlledNamedGraphSelector = namedGraphSelector as ILocallyControlledNamedGraphSelector; result = (locallyControlledNamedGraphSelector == null ? TransformCollection(result, requestInfo.Url, totalItems, skip, take) : TransformColectionWithLock(locallyControlledNamedGraphSelector, result, requestInfo, totalItems, skip, take)); return(Task.FromResult(result)); }
/// <inheritdoc /> public ResponseInfo ComposeResponse(IRequestMapping requestMapping, object output, params object[] arguments) { if (requestMapping == null) { throw new ArgumentNullException("requestMapping"); } arguments = arguments ?? new object[0]; ResponseInfo response = (ResponseInfo)requestMapping.Target.Response; ResponseInfo result = null; if (output is ResponseInfo) { if ((result = (ResponseInfo)output) != response) { result.Headers.Merge(response.Headers); } } else { bool success = false; var parameters = requestMapping.Operation.UnderlyingMethod.GetParameters(); var resultingValues = arguments.Where((item, index) => parameters[index].IsOut).ToList(); if (requestMapping.Operation.UnderlyingMethod.ReturnParameter != null) { resultingValues.Add(output); } if (requestMapping.Target.GetType().GetImplementationOfAny(typeof(IController <>), typeof(IAsyncController <>)) != null) { result = HandleCrudRequest(requestMapping, resultingValues, arguments, out success); } if (!success) { result = MakeResponse(requestMapping, resultingValues); } } if (result == response) { result.Headers.ContentType = StringConverter.TextPlain; } result.Status = (result.Status == 0 ? HttpStatusCode.OK : result.Status); return(result); }
/// <inheritdoc /> public ResponseInfo ComposeResponse(IRequestMapping requestMapping, object output, params object[] arguments) { if (requestMapping == null) { throw new ArgumentNullException("requestMapping"); } arguments = arguments ?? new object[0]; ResponseInfo response = (ResponseInfo)requestMapping.Target.Response; ResponseInfo result = null; if (output is ResponseInfo) { if ((result = (ResponseInfo)output) != response) { result.Headers.Merge(response.Headers); } } else { bool success = false; var parameters = requestMapping.Operation.UnderlyingMethod.GetParameters(); var resultingValues = arguments.Where((item, index) => parameters[index].IsOut).ToList(); if (requestMapping.Operation.UnderlyingMethod.ReturnParameter != null) { resultingValues.Add(output); } if (requestMapping.Target.GetType().GetImplementationOfAny(typeof(IController<>), typeof(IAsyncController<>)) != null) { result = HandleCrudRequest(requestMapping, resultingValues, arguments, out success); } if (!success) { result = MakeResponse(requestMapping, resultingValues); } } if (result == response) { result.Headers.ContentType = StringConverter.TextPlain; } result.Status = (result.Status == 0 ? HttpStatusCode.OK : result.Status); return result; }
/// <inheritdoc /> public object[] BindArguments(RequestInfo request, IRequestMapping requestMapping) { if (request == null) { throw new ArgumentNullException("request"); } if (requestMapping == null) { throw new ArgumentNullException("requestMapping"); } var result = new List <object>(); IDictionary <RequestInfo, RequestInfo[]> multipartBodies = new Dictionary <RequestInfo, RequestInfo[]>(); int index = 0; foreach (var parameter in requestMapping.Operation.UnderlyingMethod.GetParameters()) { var argument = (ValueInfo)requestMapping.Operation.Results.FirstOrDefault(item => item.Parameter.Equals(parameter)) ?? requestMapping.Operation.Arguments.FirstOrDefault(item => item.Parameter.Equals(parameter)); object value; if (!argument.Parameter.IsOut) { value = BindArgument(request, requestMapping, (ArgumentInfo)argument, index, multipartBodies); if ((value == null) && (argument.Parameter.DefaultValue != null)) { value = argument.Parameter.DefaultValue; requestMapping.ArgumentSources[index] = ArgumentValueSources.Default; } else { requestMapping.ArgumentSources[index] = ArgumentValueSources.Bound; } } else { value = (argument.Parameter.ParameterType.IsValueType ? Activator.CreateInstance(argument.Parameter.ParameterType) : null); requestMapping.ArgumentSources[index] = ArgumentValueSources.Default; } result.Add(value); index++; } return(result.ToArray()); }
/// <inheritdoc /> public Task<object> Transform(IRequestMapping requestMapping, IRequestInfo request, object result, object[] arguments) { RequestInfo requestInfo; MethodInfo underlyingMethod; if (!CanOutputHypermedia((underlyingMethod = requestMapping.Operation.UnderlyingMethod).ReturnType, requestInfo = request as RequestInfo)) { return Task.FromResult(result); } int totalItems = ((IEnumerable)result).Cast<object>().Count(); int skip = 0; int take = 0; bool canOutputHypermedia = false; KeyValuePair<Verb, MethodInfo> method; if ((requestMapping.Target.GetType().GetImplementationOfAny(typeof(IController<>), typeof(IAsyncController<>)) != null) && (!Equals(method = requestMapping.Target.GetType().DiscoverCrudMethods().FirstOrDefault(entry => entry.Value == underlyingMethod), default(KeyValuePair<Verb, MethodInfo>)))) { switch (method.Key.ToString()) { case "": var parameters = underlyingMethod.GetParameters(); var resultingValues = arguments.Where((item, index) => parameters[index].IsOut).ToList(); totalItems = (resultingValues.Count > 0 ? (int)resultingValues[0] : -1); if ((arguments[1] != null) && (arguments[2] != null)) { skip = (int)arguments[1]; take = ((take = (int)arguments[2]) == 0 ? 0 : Math.Min(take, totalItems)); canOutputHypermedia = (requestMapping.ArgumentSources[1] == ArgumentValueSources.Bound) && (requestMapping.ArgumentSources[2] == ArgumentValueSources.Bound); } break; } } if (!canOutputHypermedia) { return Task.FromResult(result); } var namedGraphSelector = _namedGraphSelectorFactory.NamedGraphSelector; ILocallyControlledNamedGraphSelector locallyControlledNamedGraphSelector = namedGraphSelector as ILocallyControlledNamedGraphSelector; result = (locallyControlledNamedGraphSelector == null ? TransformCollection(result, requestInfo.Url, totalItems, skip, take) : TransformColectionWithLock(locallyControlledNamedGraphSelector, result, requestInfo, totalItems, skip, take)); return Task.FromResult(result); }
private object BindArgument(RequestInfo request, IRequestMapping requestMapping, ArgumentInfo parameter, int index, IDictionary <RequestInfo, RequestInfo[]> multipartBodies) { Type parameterSourceArgumentBinderType = typeof(IParameterSourceArgumentBinder <>).MakeGenericType(parameter.Source.GetType()); IParameterSourceArgumentBinder argumentBinder = (from binder in _parameterSourceArgumentBinders where (parameterSourceArgumentBinderType.IsInstanceOfType(binder)) || (binder.GetType().GetInterfaces().Any(type => parameterSourceArgumentBinderType.IsAssignableFrom(type))) select binder).FirstOrDefault(); if (argumentBinder == null) { return(null); } var arguments = new object[] { request, (RequestMapping)requestMapping, parameter.Parameter, index, parameter.Source, multipartBodies }; ArgumentBindingContext context = (ArgumentBindingContext)typeof(ArgumentBindingContext <>) .MakeGenericType(parameter.Source.GetType()) .GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .First() .Invoke(arguments); try { return(argumentBinder.GetArgumentValue(context)); } catch (Exception exception) { throw new ArgumentException(String.Format("Could not convert argument '{0}'.", parameter.VariableName), exception); } }
private ResponseInfo MakeGetResponse(IRequestMapping requestMapping, object resultingValue) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; if (resultingValue == null) { result.Status = HttpStatusCode.NotFound; return result; } result = ObjectResponseInfo<object>.CreateInstance(result.Encoding, result.Request, resultingValue.GetType(), resultingValue, _converterProvider, result.Headers); return result; }
private ResponseInfo MakeResponse(IRequestMapping requestMapping, IList<object> resultingValues) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; var bodyValues = new List<KeyValuePair<ResultInfo, object>>(); var headerValues = new List<KeyValuePair<ResultInfo, object>>(); requestMapping.Operation.Results.ForEach((resultValue, index) => (resultValue.Target is ToHeaderAttribute ? headerValues : bodyValues).Add(new KeyValuePair<ResultInfo, object>(resultValue, resultingValues[index]))); switch (bodyValues.Count) { case 0: break; case 1: var bodyValue = bodyValues[0]; result = ObjectResponseInfo<object>.CreateInstance(result.Encoding, result.Request, bodyValue.Value.GetType(), bodyValue.Value, _converterProvider, result.Headers); break; default: result = new MultiObjectResponseInfo(result.Encoding, result.Request, bodyValues.Select(item => item.Value), _converterProvider, result.Headers); break; } headerValues.ForEach(value => result.Headers.Add(new Header( ((ToHeaderAttribute)value.Key.Target).Name, String.Format(((ToHeaderAttribute)value.Key.Target).Format, _converterProvider.ConvertFrom(value.Value))))); return result; }
private ResponseInfo HandleCrudRequest(IRequestMapping requestMapping, IList<object> resultingValues, object[] arguments, out bool success) { success = true; var methods = requestMapping.Target.GetType().DiscoverCrudMethods(); var method = methods.FirstOrDefault(entry => entry.Value == requestMapping.Operation.UnderlyingMethod); if (!Equals(method, default(KeyValuePair<Verb, MethodInfo>))) { switch (method.Key.ToString()) { case "": var type = requestMapping.Operation.UnderlyingMethod.ReturnType; var items = (resultingValues.Count > 1 ? (IEnumerable)resultingValues[1] : new[] { new object[0].MakeInstance(type, type.GetItemType()) }); var totalItems = (resultingValues.Count > 0 ? (int)resultingValues[0] : -1); return MakeListResponse(requestMapping, items, arguments, totalItems); case "GET": return MakeGetResponse(requestMapping, (resultingValues.Count > 0 ? resultingValues[resultingValues.Count - 1] : null)); case "POST": return MakePostResponse(requestMapping, (resultingValues.Count > 0 ? resultingValues[0] : null)); case "PUT": case "DELETE": return MakeDeleteResponse(requestMapping); } } success = false; return null; }
private ResponseInfo MakeDeleteResponse(IRequestMapping requestMapping) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; result.Status = HttpStatusCode.NoContent; return result; }
private ResponseInfo MakePostResponse(IRequestMapping requestMapping, object value) { ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; if (value == null) { result.Status = HttpStatusCode.BadRequest; return result; } Type controllerType = null; var controllerDescriptor = (from controller in _controllerDescriptors.Value from operation in controller.Operations where operation.Equals(requestMapping.Operation) let type = controllerType = operation.UnderlyingMethod.ReflectedType select controller).FirstOrDefault(); if (controllerDescriptor == null) { throw new InvalidOperationException(String.Format("Cannot determine the default GET request handler for '{0}'.", requestMapping.Target.GetType())); } var getMethod = (from @interface in controllerType.GetInterfaces() where (@interface.IsGenericType) && (@interface.GetGenericTypeDefinition() == typeof(IReadController<,>)) from method in controllerType.GetInterfaceMap(@interface).TargetMethods join operation in controllerDescriptor.Operations on method equals operation.UnderlyingMethod select operation).First(); result.Headers.Add(new Header(Header.Location, getMethod.UrlTemplate.Replace("{" + getMethod.Arguments.First().VariableName + "}", value.ToString()))); result.Status = HttpStatusCode.Created; return result; }
private ResponseInfo MakeListResponse(IRequestMapping requestMapping, IEnumerable resultingValues, object[] arguments, int totalItems = 0) { var status = HttpStatusCode.OK; ResponseInfo result = (ResponseInfo)requestMapping.Target.Response; if ((arguments[1] != null) && (arguments[2] != null)) { int skip = (int)arguments[1]; int take = (int)arguments[2]; take = (take == 0 ? totalItems : Math.Min(take, resultingValues.Cast<object>().Count())); var contentRangeHeaderValue = String.Format("members {0}-{1}/{2}", skip, Math.Max(0, take - 1), totalItems); result.Headers.Add(new Header("Content-Range", contentRangeHeaderValue)); status = HttpStatusCode.PartialContent; } result = ObjectResponseInfo<object>.CreateInstance( result.Encoding, result.Request, requestMapping.Operation.UnderlyingMethod.ReturnType, resultingValues, _converterProvider, result.Headers); result.Status = status; return result; }