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); }
/// <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); }