コード例 #1
0
        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);
        }
コード例 #2
0
        private ResponseInfo MakeDeleteResponse(IRequestMapping requestMapping)
        {
            ResponseInfo result = (ResponseInfo)requestMapping.Target.Response;

            result.Status = HttpStatusCode.NoContent;
            return(result);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
 public static bool IsHttpMethod(this IRequestMapping requestMapping, string httpMethod)
 {
     if (requestMapping == null)
     {
         return(false);
     }
     return(string.Equals(httpMethod, requestMapping.GetMethod(), StringComparison.OrdinalIgnoreCase));
 }
コード例 #7
0
 public static bool IsSupportRequestContent(this IRequestMapping requestMapping)
 {
     return
         (requestMapping.IsHttpMethod(HttpMethod.Post) ||
          requestMapping.IsHttpMethod(HttpMethod.Put) ||
          requestMapping.IsHttpMethod(HttpMethod.Delete) ||
          requestMapping.IsHttpMethod("PATCH")
         );
 }
コード例 #8
0
        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);
        }
コード例 #9
0
        /// <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));
        }
コード例 #10
0
        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);
        }
コード例 #11
0
        /// <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));
        }
コード例 #12
0
        /// <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);
        }
コード例 #13
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
        /// <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;
        }
コード例 #14
0
        /// <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());
        }
コード例 #15
0
        /// <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);
        }
コード例 #16
0
        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);
            }
        }
コード例 #17
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
        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;
        }
コード例 #18
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
        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;
        }
コード例 #19
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
        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;
        }
コード例 #20
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
 private ResponseInfo MakeDeleteResponse(IRequestMapping requestMapping)
 {
     ResponseInfo result = (ResponseInfo)requestMapping.Target.Response;
     result.Status = HttpStatusCode.NoContent;
     return result;
 }
コード例 #21
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
        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;
        }
コード例 #22
0
ファイル: ResponseComposer.cs プロジェクト: alien-mcl/URSA
        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;
        }