Ejemplo n.º 1
0
        static void SendJsonResponse(ServiceHandlerRequestContext context, object value)
        {
            var response = context.HttpResponse;

            response.ContentType = "application/json; charset=utf-8";

            JsonSerializer serializer = new JsonSerializer();

            if (context.ServiceInstanceConfiguration.JsonFormatMode == JsonFormatModes.CamelCase)
            {
                serializer.ContractResolver = CamelCaseNamingStrategy;
            }
            else if (context.ServiceInstanceConfiguration.JsonFormatMode == JsonFormatModes.SnakeCase)
            {
                serializer.ContractResolver = SnakeCaseNamingStrategy;
            }

#if DEBUG
            serializer.Formatting = Formatting.Indented;
#endif

            using (var sw = new StreamWriter(response.Body))
            {
                using (JsonWriter writer = new JsonTextWriter(sw))
                {
                    serializer.Serialize(writer, value);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Main entry point method that handles processing the active request
        /// </summary>
        /// <returns></returns>
        public async Task ProcessRequest()
        {
            var context = new ServiceHandlerRequestContext()
            {
                HttpRequest  = HttpRequest,
                HttpResponse = HttpResponse,
                HttpContext  = HttpContext,
                ServiceInstanceConfiguration = ServiceInstanceConfiguration,
                MethodContext = MethodContext,
                Url           = new ServiceHandlerRequestContextUrl()
                {
                    Url         = HttpRequest.GetDisplayUrl(),
                    UrlPath     = HttpRequest.Path.Value,
                    QueryString = HttpRequest.QueryString,
                    HttpMethod  = HttpRequest.Method.ToUpper()
                }
            };

            try
            {
                if (context.ServiceInstanceConfiguration.HttpsMode == ControllerHttpsMode.RequireHttps &&
                    HttpRequest.Scheme != "https")
                {
                    throw new UnauthorizedAccessException(Resources.ServiceMustBeAccessedOverHttps);
                }

                if (ServiceInstanceConfiguration.OnAuthorize != null)
                {
                    if (!await ServiceInstanceConfiguration.OnAuthorize(context))
                    {
                        throw new UnauthorizedAccessException("Not authorized to access this request");
                    }
                }


                if (ServiceInstanceConfiguration.OnBeforeMethodInvoke != null)
                {
                    await ServiceInstanceConfiguration.OnBeforeMethodInvoke(context);
                }

                await ExecuteMethod(context);

                ServiceInstanceConfiguration.OnAfterMethodInvoke?.Invoke(context);

                if (string.IsNullOrEmpty(context.ResultJson))
                {
                    context.ResultJson = JsonSerializationUtils.Serialize(context.ResultValue);
                }

                SendJsonResponse(context, context.ResultValue);
            }
            catch (Exception ex)
            {
                var error = new ErrorResponse(ex);
                SendJsonResponse(context, error);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="handlerContext"></param>
        /// <returns></returns>
        async Task ExecuteMethod(ServiceHandlerRequestContext handlerContext)
        {
            var serviceConfig  = ServiceHandlerConfiguration.Current;
            var methodToInvoke = handlerContext.MethodContext.MethodInfo;
            var serviceType    = handlerContext.ServiceInstanceConfiguration.ServiceType;


            var httpVerb = handlerContext.HttpRequest.Method;

            if (httpVerb == "OPTIONS" && serviceConfig.Cors.UseCorsPolicy)
            {
                // emty response - ASP.NET will provide CORS headers via applied policy
                handlerContext.HttpResponse.StatusCode = StatusCodes.Status204NoContent;
                return;
            }

            // Let DI create the Service instance
            var inst = HttpContext.RequestServices.GetService(serviceType);

            if (inst == null)
            {
                throw new InvalidOperationException(string.Format(Resources.UnableToCreateTypeInstance, serviceType));
            }

            var principal = HttpContext.User;

            UserPrincipalHelper.AddPrincipal(inst, principal);

            if (MethodContext.AuthorizationRoles != null && MethodContext.AuthorizationRoles.Count > 0)
            {
                ValidateRoles(MethodContext.AuthorizationRoles, principal);
            }

            try
            {
                var parameterList = GetMethodParameters(handlerContext);

                if (!handlerContext.MethodContext.IsAsync)
                {
                    handlerContext.ResultValue = methodToInvoke.Invoke(inst, parameterList);
                }
                else
                {
                    handlerContext.ResultValue = await(dynamic) methodToInvoke.Invoke(inst, parameterList);
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(string.Format(Resources.UnableToExecuteMethod, methodToInvoke.Name,
                                                                  ex.Message));
            }
            finally
            {
                UserPrincipalHelper.RemovePrincipal(inst);
            }
        }
        public static async Task SendJsonResponseAsync(ServiceHandlerRequestContext context, object value)
        {
            var response = context.HttpResponse;

            response.ContentType = "application/json; charset=utf-8";

            var options = new JsonSerializerOptions();

            if (context.ServiceInstanceConfiguration.JsonFormatMode == JsonFormatModes.CamelCase)
            {
                options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            }
            //else if (context.ServiceInstanceConfiguration.JsonFormatMode == JsonFormatModes.SnakeCase)
            //    serializer.ContractResolver = SnakeCaseNamingStrategy;

#if DEBUG
            options.WriteIndented = true;
#endif

            var inputType = value.GetType();
            await JsonSerializer.SerializeAsync(response.Body, value, inputType, options);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Retrieve parameters from body and URL parameters
        /// </summary>
        /// <param name="handlerContext"></param>
        /// <returns></returns>
        private object[] GetMethodParameters(ServiceHandlerRequestContext handlerContext)
        {
            // parameter parsing
            var    parameterList = new object[] { };
            object result        = null;

            // simplistic - no parameters or single body post parameter
            var paramInfos = handlerContext.MethodContext.MethodInfo.GetParameters();

            if (paramInfos.Length > 1)
            {
                throw new ArgumentNullException(string.Format(
                                                    Resources.OnlySingleParametersAreAllowedOnServiceMethods,
                                                    MethodContext.MethodInfo.Name));
            }

            // if there is a parameter create and de-serialize, then add url parameters
            if (paramInfos.Length == 1)
            {
                var parm = paramInfos[0];

                // First Deserialize from body if any
                JsonSerializer serializer = new JsonSerializer();

                // there's always 1 parameter
                object parameterData = null;
                if (HttpRequest.ContentLength == null || HttpRequest.ContentLength < 1)
                {
                    // if no content create an empty one
                    parameterData = ReflectionUtils.CreateInstanceFromType(parm.ParameterType);
                }
                else
                {
                    using (var sw = new StreamReader(HttpRequest.Body))
                        using (JsonReader reader = new JsonTextReader(sw))
                        {
                            parameterData = serializer.Deserialize(reader, parm.ParameterType);
                        }
                }

                // Map named URL parameters to properties
                if (RouteData != null)
                {
                    foreach (var kv in RouteData.Values)
                    {
                        var prop = parm.ParameterType.GetProperty(kv.Key,
                                                                  BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty |
                                                                  BindingFlags.IgnoreCase);
                        if (prop != null)
                        {
                            try
                            {
                                var val = ReflectionUtils.StringToTypedValue(kv.Value as string, prop.PropertyType);
                                ReflectionUtils.SetProperty(parameterData, kv.Key, val);
                            }
                            catch
                            {
                                throw new InvalidOperationException(
                                          string.Format("Unable set parameter from URL segment for property: {0}", kv.Key));
                            }
                        }
                    }
                }

                parameterList = new[] { parameterData };
            }
            return(parameterList);
        }
        /// <summary>
        /// Main entry point method that handles processing the active request
        /// </summary>
        /// <returns></returns>
        public async Task ProcessRequest()
        {
            var context = new ServiceHandlerRequestContext
            {
                HttpRequest  = HttpRequest,
                HttpResponse = HttpResponse,
                HttpContext  = HttpContext,
                ServiceInstanceConfiguration = ServiceInstanceConfiguration,
                MethodContext = MethodContext,
                Url           = new ServiceHandlerRequestContextUrl
                {
                    Url         = HttpRequest.GetDisplayUrl(),
                    UrlPath     = HttpRequest.Path.Value,
                    QueryString = HttpRequest.QueryString,
                    HttpMethod  = HttpRequest.Method.ToUpper()
                }
            };

            try
            {
                if (context.ServiceInstanceConfiguration.HttpsMode == ControllerHttpsMode.RequireHttps && HttpRequest.Scheme != "https")
                {
                    throw new UnauthorizedAccessException(Resources.ServiceMustBeAccessedOverHttps);
                }

                if (ServiceInstanceConfiguration.OnAuthorize != null)
                {
                    if (!await ServiceInstanceConfiguration.OnAuthorize(context))
                    {
                        throw new UnauthorizedAccessException("Not authorized to access this request");
                    }
                }

                if (ServiceInstanceConfiguration.OnBeforeMethodInvoke != null)
                {
                    await ServiceInstanceConfiguration.OnBeforeMethodInvoke(context);
                }

                await ExecuteMethod(context);

                ServiceInstanceConfiguration.OnAfterMethodInvoke?.Invoke(context);

                if (context.ResultValue is IFileResponse fileResponse)
                {
                    // This is a special case in which we stream the file back low level (side-stepping any kind of JSON serialization)
                    context.HttpResponse.ContentType = fileResponse.ContentType;
                    context.HttpResponse.Headers.Add("Content-Disposition", $"inline; filename=\"{fileResponse.FileName.Trim()}\"");
                    context.HttpResponse.Headers.Add("x-powered-by", "CODE Framework - codeframework.io");
                    await context.HttpResponse.Body.WriteAsync(fileResponse.FileBytes, 0, fileResponse.FileBytes.Length);
                }
                else
                {
                    if (string.IsNullOrEmpty(context.ResultJson))
                    {
                        var options = new JsonSerializerOptions();

                        if (context.ServiceInstanceConfiguration.JsonFormatMode == JsonFormatModes.CamelCase)
                        {
                            options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
                        }

#if DEBUG
                        options.WriteIndented = true;
#endif

                        var inputType = context.ResultValue.GetType();
                        context.ResultJson = JsonSerializer.Serialize(context.ResultValue, inputType, options);

                        context.HttpResponse.Headers.Add("x-powered-by", "CODE Framework - codeframework.io");
                    }

                    await SendJsonResponseAsync(context, context.ResultValue);
                }
            }
            catch (Exception ex)
            {
                var error = new ErrorResponse(ex);
                await SendJsonResponseAsync(context, error);
            }
        }
        /// <summary>
        /// Retrieve parameters from body and URL parameters
        /// </summary>
        /// <param name="handlerContext"></param>
        /// <returns></returns>
        private async Task <object[]> GetMethodParametersAsync(ServiceHandlerRequestContext handlerContext)
        {
            // parameter parsing
            var parameterList = new object[] { };

            // simplistic - no parameters or single body post parameter
            var paramInfos = handlerContext.MethodContext.MethodInfo.GetParameters();

            if (paramInfos.Length > 1)
            {
                throw new ArgumentNullException(string.Format(Resources.OnlySingleParametersAreAllowedOnServiceMethods, MethodContext.MethodInfo.Name));
            }

            // if there is a parameter create and de-serialize, then add url parameters
            if (paramInfos.Length != 1)
            {
                return(parameterList);
            }
            var parameter = paramInfos[0];

            // First Deserialize from body if any

            // there's always 1 parameter
            object parameterData;

            if (HttpRequest.ContentLength == null || HttpRequest.ContentLength < 1)
            {
                parameterData = ObjectHelper.CreateInstanceFromType(parameter.ParameterType); // if no content create an empty one
            }
            else
            {
                parameterData = await JsonSerializer.DeserializeAsync(HttpRequest.Body, parameter.ParameterType);
            }

            // We map all parameters passed as named parameters in the URL to their respective properties
            foreach (var key in handlerContext.HttpRequest.Query.Keys)
            {
                var property = parameter.ParameterType.GetProperty(key, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.IgnoreCase);
                if (property == null)
                {
                    continue;
                }
                try
                {
                    var urlParameterValue = handlerContext.HttpRequest.Query[key].ToString();
                    var parameterValue    = UrlParameterToValue(urlParameterValue, property.PropertyType);
                    ObjectHelper.SetPropertyValue(parameterData, key, parameterValue);
                }
                catch
                {
                    throw new InvalidOperationException($"Unable set parameter from URL segment for property: {key}");
                }
            }

            // Map inline URL parameters defined in the route to properties.
            // Note: Since this is done after the named parameters above, parameters that are part of the route definition win out over simple named parameters
            if (RouteData != null)
            {
                foreach (var(key, value) in RouteData.Values)
                {
                    var property = parameter.ParameterType.GetProperty(key, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.IgnoreCase);
                    if (property == null)
                    {
                        continue;
                    }
                    try
                    {
                        var parameterValue = UrlParameterToValue(value as string, property.PropertyType);
                        ObjectHelper.SetPropertyValue(parameterData, key, parameterValue);
                    }
                    catch
                    {
                        throw new InvalidOperationException($"Unable set parameter from URL segment for property: {key}");
                    }
                }
            }

            parameterList = new[] { parameterData };

            return(parameterList);
        }