public async Task NegativeResponsesAreValid()
        {
            var jsonOpts = LikePharmaClientOptions.CreateDefaultJsonSerializerOptions();
            var protSet  = ProtocolSettings.CreateOlekstra();

            var req = new GetDiscountRequest
            {
                PosId       = "12345",
                PharmacyId  = "123",
                CardNumber  = "1234567890",
                PhoneNumber = "+79000000000",
                AnyData     = "abc",
            };

            var jsonText  = LikePharmaClient.SerializeJson(req, protSet, jsonOpts);
            var jsonBytes = Encoding.UTF8.GetBytes(jsonText);

            using var body = new MemoryStream();
            body.Write(jsonBytes, 0, jsonBytes.Length);
            body.Position = 0;

            context.Request.Method      = "POST";
            context.Request.Path        = "/get_discount";
            context.Request.ContentType = "application/json";
            context.Request.Body        = body;

            context.Response.Body = new MemoryStream();

            await middleware.InvokeAsync(context).ConfigureAwait(false);

            Assert.Equal(200, context.Response.StatusCode);

            context.Response.Body.Position = 0;

            using var sr = new StreamReader(context.Response.Body);
            var respText = await sr.ReadToEndAsync().ConfigureAwait(false);

            var resp = LikePharmaClient.DeserializeJson <GetDiscountResponse>(respText, protSet, jsonOpts);

            var validator = new LikePharmaValidator(protSet);
            var valid     = validator.TryValidateObject(resp, out var results);

            Assert.Empty(results);
            Assert.True(valid);
        }
Esempio n. 2
0
        /// <summary>
        /// Обработчик запроса: считывает и десериализует запрос, валидирует его, вызывает обработчик, вылидирует ответ, отправляет ответ.
        /// </summary>
        /// <typeparam name="TRequest">Тип запроса.</typeparam>
        /// <typeparam name="TResponse">Тип ответа.</typeparam>
        /// <param name="processor">Обработчик.</param>
        /// <param name="negativeResponseTemplate">Шаблон для создания отрицательного ответа (в случае ошибок валидации).</param>
        /// <param name="httpRequest">HTTP-запрос (из которого считывать данные).</param>
        /// <param name="httpResponse">HTTP-ответ (куда записывать результат).</param>
        /// <param name="user">Текущий (авторизованный) пользователь.</param>
        /// <returns>Awaitable Task.</returns>
        public async Task Process <TRequest, TResponse>(
            Func <TRequest, TUser, Task <TResponse> > processor,
            Func <TRequest, int, string, TResponse> negativeResponseTemplate,
            HttpRequest httpRequest,
            HttpResponse httpResponse,
            TUser user)
            where TRequest : RequestBase <TResponse>
            where TResponse : ResponseBase, new()
        {
            processor = processor ?? throw new ArgumentNullException(nameof(processor));
            negativeResponseTemplate = negativeResponseTemplate ?? throw new ArgumentNullException(nameof(negativeResponseTemplate));
            httpRequest  = httpRequest ?? throw new ArgumentNullException(nameof(httpRequest));
            httpResponse = httpResponse ?? throw new ArgumentNullException(nameof(httpResponse));
            user         = user ?? throw new ArgumentNullException(nameof(user));

            TRequest  req;
            TResponse resp;

            async Task WriteResponse(TResponse response)
            {
                httpResponse.ContentType = ContentTypeJson;
                var json = LikePharmaClient.SerializeJson(response, options.ProtocolSettings, options.JsonSerializerOptions);

                using var sw = new StreamWriter(httpResponse.Body, leaveOpen: true);
                await sw.WriteAsync(json).ConfigureAwait(false);
            }

            try
            {
                using var sr = new StreamReader(httpRequest.Body, System.Text.Encoding.UTF8);
                var json = await sr.ReadToEndAsync().ConfigureAwait(false);

                req = LikePharmaClient.DeserializeJson <TRequest>(json, options.ProtocolSettings, options.JsonSerializerOptions);
            }
            catch (JsonException ex)
            {
                logger.LogWarning(ex, "Ошибка при разборе входящего JSON: " + ex.Message);
                httpResponse.StatusCode  = StatusCodes.Status400BadRequest;
                httpResponse.ContentType = ContentTypeTextUtf8;
                await httpResponse.WriteAsync(string.Format(CultureInfo.InvariantCulture, Messages.Status400BadRequest_InvalidJson_ResponseText, ex.Message)).ConfigureAwait(false);

                return;
            }

            if (!validator.TryValidateObject(req, out var results))
            {
                resp = negativeResponseTemplate(req, StatusCodes.Status400BadRequest, results.First().ErrorMessage);
                await WriteResponse(resp).ConfigureAwait(false);

                return;
            }

            resp = await processor(req, user).ConfigureAwait(false);

            if (!validator.TryValidateObject(resp, out results))
            {
                logger.LogDebug(JsonSerializer.Serialize(resp, options.JsonSerializerOptions));

                var errors = string.Join(Environment.NewLine, results.Select(x => x.MemberNames.FirstOrDefault() + " " + x.ErrorMessage));
                logger.LogWarning("Errors: " + errors);

                var ex = new ApplicationException(Messages.PreparedResponseIsInvalid);
                ex.Data.Add("Errors", errors);
                throw ex;
            }

            await WriteResponse(resp).ConfigureAwait(false);
        }