Example #1
0
        /// <summary>
        /// Обработка запроса
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private void HandleContext(HttpListenerContext context)
        //private async Task HandleContextAsync(HttpListenerContext context)
        {
            var request  = context.Request;
            var response = context.Response;

            // Получаем имя контроллера из запроса
            string controllerName = request.Url.Segments[1].Replace("/", "").ToLower();
            // Создаем контроллев используя фабрику
            Controller controller = controllerFactory.Create(controllerName);

            if (controller == null)
            {
                Console.WriteLine("controller is not found");
                response.StatusCode = (int)HttpStatusCode.NotFound;
                using (Stream stream = response.OutputStream) { }
                return;
            }

            // Получаем имя метода из запроса
            string methodName = request.Url.Segments[2].Replace("/", "");

            // Получаем строковые значение параметров запроса
            string[] strMethodParams = request.Url
                                       .Segments
                                       .Skip(3)
                                       .Select(s => s.Replace("/", ""))
                                       .ToArray();

            // Ищем методы контроллера
            var methods = controller
                          .GetType()
                          .GetMethods()
                          // поиск по имени
                          .Where(m => m.Name.ToLower() == methodName.ToLower())
                          // по соответствию типу запроса
                          .Where(m => m.GetCustomAttributes(typeof(Http), true)
                                 .Any(attr =>
                                      ((Http)attr).Type.ToLower() == request.HttpMethod.ToLower()) ||
                                 (m.GetCustomAttributes(typeof(Http), true).FirstOrDefault() == null &&
                                  request.HttpMethod.ToLower() == "get"
                                 )
                                 )
                          // по количеству параметров
                          .Where(m => m.GetParameters().Length == strMethodParams.Length ||
                                 (strMethodParams.Length ==
                                  m.GetParameters().Length
                                  - m.GetParameters().Where(mp => mp.HasDefaultValue).Count()
                                  - (m.GetParameters()
                                     .Any(p => p.GetCustomAttributes(typeof(FromBody), true)
                                          .FirstOrDefault() != null) ? 1 : 0
                                     )
                                 )
                                 );

            // Берем первый метода из найденных
            var method = methods.FirstOrDefault();

            if (method == null)
            {
                Console.WriteLine("method is not found");
                response.StatusCode = (int)HttpStatusCode.NotFound;
                using (Stream stream = response.OutputStream) { }
                return;
            }

            // Получеам информацию о параметрах найденного метода
            var methodParamsInfo = method.GetParameters();

            // Массив параметров, используемый для вызова найденного параметра
            object[] methodParamsValues = new object[methodParamsInfo.Length];

            // Счетчик, нужен для пропуска параметров метода с аттрибутом FromBody
            int k = 0;
            // Определение настроек сериализации
            var jsonSerializerSettings = new JsonSerializerSettings();

            jsonSerializerSettings.ReferenceLoopHandling  = ReferenceLoopHandling.Error;
            jsonSerializerSettings.CheckAdditionalContent = true;
            jsonSerializerSettings.MissingMemberHandling  = MissingMemberHandling.Error;

            // Определение параметров methodParamValues метода
            for (int i = 0; i < methodParamsInfo.Length; i++)
            {
                // Проверка на значение параметра по умолчанию
                if (methodParamsInfo[i].HasDefaultValue)
                {
                    methodParamsValues[i] = methodParamsInfo[i].DefaultValue;
                    continue;
                }

                // Если параметр имеет аттрибут FromBody
                if (methodParamsInfo[i].GetCustomAttributes(typeof(FromBody), true).FirstOrDefault() != null)
                {
                    k++;
                    // Если параметр запрос иметт тело и метод имеет аттрибут Http c типом запроса POST или PUT
                    if (request.HasEntityBody && method.GetCustomAttributes(typeof(Http), true)
                        .Any(attr => ((Http)attr).Type.ToLower() == "post" ||
                             ((Http)attr).Type.ToLower() == "put")
                        )
                    {
                        try
                        {
                            // Десериализация json-тела запроса

                            using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
                                methodParamsValues[i] = JsonConvert.DeserializeObject(reader.ReadToEnd(), methodParamsInfo[i].ParameterType);
                        }
                        catch (Exception exc)
                        {
                            Console.WriteLine("json error");
                            Console.WriteLine($"{exc.Source}\n{exc.Message}");
                        }
                    }
                    else
                    {
                        methodParamsValues[i] = null;
                    }
                }
                // Присваивание значений параматрам метода если они не имеют атрибут FromBody
                else
                {
                    methodParamsValues[i] = Convert.ChangeType(strMethodParams[i - k], methodParamsInfo[i].ParameterType);
                }
                if (methodParamsValues[i] == null)
                {
                    Console.WriteLine("is null");
                }
            }

            // Если метод не имеет возвращаемого значения, то просто вызываем метод
            if (method.ReturnType.Name == "Void")
            {
                method.Invoke(controller, methodParamsValues);
                response.StatusCode = (int)HttpStatusCode.OK;
                using (Stream strema = response.OutputStream) { }
            }
            // если метод имеет возвращаемоге значение, то сериализуем его(значение) и посылаем клиенту
            else
            {
                object answer = method.Invoke(controller, methodParamsValues);
                if (answer == null)
                {
                    Console.WriteLine("answer is empty");
                    response.StatusCode = (int)HttpStatusCode.NotFound;
                    using (Stream stream = response.OutputStream) { }
                    return;
                }

                string answerJson;
                Console.WriteLine("Begin serialization");
                try
                {
                    answerJson = JsonConvert.SerializeObject(answer, jsonSerializerSettings);
                }
                catch (Exception e)
                {
                    answerJson = "";
                    Console.WriteLine($"{e.Source}\n{e.Message}");
                }
                Console.WriteLine("End serialization");
                byte[] buffer = Encoding.UTF8.GetBytes(answerJson);
                response.ContentType     = "application/json";
                response.ContentEncoding = Encoding.UTF8;
                response.ContentLength64 = buffer.Length;
                response.StatusCode      = (int)HttpStatusCode.OK;
                Stream output = response.OutputStream;
                output.Write(buffer, 0, buffer.Length);
                output.Close();
            }
            Console.WriteLine();
        }