/// <inheritdoc /> public virtual Task<InputFormatterResult> ReadAsync(InputFormatterContext context) { var request = context.HttpContext.Request; if (request.ContentLength == 0) { return InputFormatterResult.SuccessAsync(GetDefaultValueForType(context.ModelType)); } return ReadRequestBodyAsync(context); }
/// <inheritdoc /> public override bool CanRead(InputFormatterContext context) { var modelTypeInfo = context.ModelType.GetTypeInfo(); if (!typeof(IJsonPatchDocument).GetTypeInfo().IsAssignableFrom(modelTypeInfo) || !modelTypeInfo.IsGenericType) { return false; } return base.CanRead(context); }
/// <inheritdoc /> public virtual bool CanRead(InputFormatterContext context) { if (!CanReadType(context.ModelType)) { return false; } var contentType = context.HttpContext.Request.ContentType; MediaTypeHeaderValue requestContentType; if (!MediaTypeHeaderValue.TryParse(contentType, out requestContentType)) { return false; } return SupportedMediaTypes.Any(supportedMediaType => supportedMediaType.IsSubsetOf(requestContentType)); }
/// <inheritdoc /> public virtual bool CanRead(InputFormatterContext context) { if (!CanReadType(context.ModelType)) { return false; } var contentType = context.HttpContext.Request.ContentType; MediaTypeHeaderValue requestContentType; if (!MediaTypeHeaderValue.TryParse(contentType, out requestContentType)) { return false; } // Confirm the request's content type is more specific than a media type this formatter supports e.g. OK if // client sent "text/plain" data and this formatter supports "text/*". return SupportedMediaTypes.Any(supportedMediaType => { return requestContentType.IsSubsetOf(supportedMediaType); }); }
public async Task CustomSerializerSettingsObject_TakesEffect() { // Arrange // missing password property here var contentBytes = Encoding.UTF8.GetBytes("{ \"UserName\" : \"John\"}"); var logger = GetLogger(); var jsonFormatter = new JsonInputFormatter(logger); // by default we ignore missing members, so here explicitly changing it jsonFormatter.SerializerSettings = new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Error }; var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8"); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(UserLogin)); var inputFormatterContext = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await jsonFormatter.ReadAsync(inputFormatterContext); // Assert Assert.True(result.HasError); Assert.False(modelState.IsValid); var modelErrorMessage = modelState.Values.First().Errors[0].Exception.Message; Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage); }
public async Task ReadAsync_AddsModelValidationErrorsToModelState() { // Arrange var content = "{name: 'Person Name', Age: 'not-an-age'}"; var formatter = new JsonInputFormatter(); var contentBytes = Encoding.UTF8.GetBytes(content); var modelState = new ModelStateDictionary(); var httpContext = GetHttpContext(contentBytes); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: modelState, modelType: typeof(User)); // Act var result = await formatter.ReadAsync(context); // Assert Assert.True(result.HasError); Assert.Equal( "Could not convert string to decimal: not-an-age. Path 'Age', line 1, position 39.", modelState["Age"].Errors[0].Exception.Message); }
public async Task JsonFormatterReadsComplexTypes() { // Arrange var content = "{name: 'Person Name', Age: '30'}"; var formatter = new JsonInputFormatter(); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), modelType: typeof(User)); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); var userModel = Assert.IsType <User>(result.Model); Assert.Equal("Person Name", userModel.Name); Assert.Equal(30, userModel.Age); }
public async Task JsonFormatterReadsSimpleTypes(string content, Type type, object expected) { // Arrange var logger = GetLogger(); var formatter = new JsonInputFormatter(logger); var contentBytes = Encoding.UTF8.GetBytes(content); var httpContext = GetHttpContext(contentBytes); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(type); var context = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = await formatter.ReadAsync(context); // Assert Assert.False(result.HasError); Assert.Equal(expected, result.Model); }
public void CanRead_ReturnsTrueForAnySupportedContentType(string requestContentType, bool expectedCanRead) { // Arrange var loggerMock = GetLogger(); var formatter = new JsonInputFormatter(loggerMock); var contentBytes = Encoding.UTF8.GetBytes("content"); var httpContext = GetHttpContext(contentBytes, contentType: requestContentType); var provider = new EmptyModelMetadataProvider(); var metadata = provider.GetMetadataForType(typeof(string)); var formatterContext = new InputFormatterContext( httpContext, modelName: string.Empty, modelState: new ModelStateDictionary(), metadata: metadata, readerFactory: new TestHttpRequestStreamReaderFactory().CreateReader); // Act var result = formatter.CanRead(formatterContext); // Assert Assert.Equal(expectedCanRead, result); }
/// <summary> /// Reads an object from the request body. /// </summary> /// <param name="context">The <see cref="InputFormatterContext"/>.</param> /// <returns>A <see cref="Task"/> that on completion deserializes the request body.</returns> public abstract Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context);
public override bool CanRead(InputFormatterContext context) { return typeof(Representation).IsAssignableFrom(context.ModelType); }
/// <summary> /// Returns an <see cref="Encoding"/> based on <paramref name="context"/>'s /// <see cref="MediaTypeHeaderValue.Charset"/>. /// </summary> /// <param name="context">The <see cref="InputFormatterContext"/>.</param> /// <returns> /// An <see cref="Encoding"/> based on <paramref name="context"/>'s /// <see cref="MediaTypeHeaderValue.Charset"/>. <c>null</c> if no supported encoding was found. /// </returns> protected Encoding SelectCharacterEncoding(InputFormatterContext context) { var request = context.HttpContext.Request; MediaTypeHeaderValue contentType; MediaTypeHeaderValue.TryParse(request.ContentType, out contentType); if (contentType != null) { var charset = contentType.Charset; if (!string.IsNullOrWhiteSpace(charset)) { foreach (var supportedEncoding in SupportedEncodings) { if (string.Equals(charset, supportedEncoding.WebName, StringComparison.OrdinalIgnoreCase)) { return supportedEncoding; } } } } if (SupportedEncodings.Count > 0) { return SupportedEncodings[0]; } // No supported encoding was found so there is no way for us to start reading. context.ModelState.TryAddModelError( context.ModelName, Resources.FormatInputFormatterNoEncoding(GetType().FullName)); return null; }
/// <inheritdoc /> public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // Get the character encoding for the content. var effectiveEncoding = SelectCharacterEncoding(context); if (effectiveEncoding == null) { return InputFormatterResult.FailureAsync(); } var request = context.HttpContext.Request; using (var jsonReader = CreateJsonReader(context, request.Body, effectiveEncoding)) { jsonReader.CloseInput = false; var successful = true; EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs> errorHandler = (sender, eventArgs) => { successful = false; var exception = eventArgs.ErrorContext.Error; // Handle path combinations such as "" + "Property", "Parent" + "Property", or "Parent" + "[12]". var key = eventArgs.ErrorContext.Path; if (!string.IsNullOrEmpty(context.ModelName)) { if (string.IsNullOrEmpty(eventArgs.ErrorContext.Path)) { key = context.ModelName; } else if (eventArgs.ErrorContext.Path[0] == '[') { key = context.ModelName + eventArgs.ErrorContext.Path; } else { key = context.ModelName + "." + eventArgs.ErrorContext.Path; } } context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error); // Error must always be marked as handled // Failure to do so can cause the exception to be rethrown at every recursive level and // overflow the stack for x64 CLR processes eventArgs.ErrorContext.Handled = true; }; var type = context.ModelType; var jsonSerializer = CreateJsonSerializer(); jsonSerializer.Error += errorHandler; object model; try { model = jsonSerializer.Deserialize(jsonReader, type); } finally { // Clean up the error handler in case CreateJsonSerializer() reuses a serializer jsonSerializer.Error -= errorHandler; } if (successful) { return InputFormatterResult.SuccessAsync(model); } return InputFormatterResult.FailureAsync(); } }
/// <summary> /// Called during deserialization to get the <see cref="JsonReader"/>. /// </summary> /// <param name="context">The <see cref="InputFormatterContext"/> for the read.</param> /// <param name="readStream">The <see cref="Stream"/> from which to read.</param> /// <param name="effectiveEncoding">The <see cref="Encoding"/> to use when reading.</param> /// <returns>The <see cref="JsonReader"/> used during deserialization.</returns> protected virtual JsonReader CreateJsonReader( InputFormatterContext context, Stream readStream, Encoding effectiveEncoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (readStream == null) { throw new ArgumentNullException(nameof(readStream)); } if (effectiveEncoding == null) { throw new ArgumentNullException(nameof(effectiveEncoding)); } return new JsonTextReader(new StreamReader(readStream, effectiveEncoding)); }
/// <summary> /// Called during deserialization to get the <see cref="BsonReader"/>. /// </summary> /// <param name="context">The <see cref="InputFormatterContext"/> for the read.</param> /// <param name="readStream">The <see cref="Stream"/> from which to read.</param> /// <returns>The <see cref="BsonReader"/> used during deserialization.</returns> protected virtual BsonReader CreateBsonReader( InputFormatterContext context, Stream readStream) { return new BsonReader(readStream); }
/// <summary> /// Reads an object from the request body. /// </summary> /// <param name="context">The <see cref="InputFormatterContext"/>.</param> /// <returns>A <see cref="Task"/> that on completion deserializes the request body.</returns> public abstract Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context);
/// <inheritdoc /> public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { var effectiveEncoding = SelectCharacterEncoding(context); if (effectiveEncoding == null) { return InputFormatterResult.FailureAsync(); } var request = context.HttpContext.Request; using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), effectiveEncoding)) { var type = GetSerializableType(context.ModelType); var serializer = GetCachedSerializer(type); var deserializedObject = serializer.ReadObject(xmlReader); // Unwrap only if the original type was wrapped. if (type != context.ModelType) { var unwrappable = deserializedObject as IUnwrappable; if (unwrappable != null) { deserializedObject = unwrappable.Unwrap(declaredType: context.ModelType); } } return InputFormatterResult.SuccessAsync(deserializedObject); } }
/// <inheritdoc /> public override Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // Get the character encoding for the content. var effectiveEncoding = SelectCharacterEncoding(context); if (effectiveEncoding == null) { return(InputFormatterResult.FailureAsync()); } var request = context.HttpContext.Request; using (var streamReader = context.ReaderFactory(request.Body, effectiveEncoding)) { using (var jsonReader = new JsonTextReader(streamReader)) { jsonReader.ArrayPool = _charPool; jsonReader.CloseInput = false; var successful = true; EventHandler <Newtonsoft.Json.Serialization.ErrorEventArgs> errorHandler = (sender, eventArgs) => { successful = false; var exception = eventArgs.ErrorContext.Error; // Handle path combinations such as "" + "Property", "Parent" + "Property", or "Parent" + "[12]". var key = eventArgs.ErrorContext.Path; if (!string.IsNullOrEmpty(context.ModelName)) { if (string.IsNullOrEmpty(eventArgs.ErrorContext.Path)) { key = context.ModelName; } else if (eventArgs.ErrorContext.Path[0] == '[') { key = context.ModelName + eventArgs.ErrorContext.Path; } else { key = context.ModelName + "." + eventArgs.ErrorContext.Path; } } var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path); context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata); _logger.JsonInputException(eventArgs.ErrorContext.Error); // Error must always be marked as handled // Failure to do so can cause the exception to be rethrown at every recursive level and // overflow the stack for x64 CLR processes eventArgs.ErrorContext.Handled = true; }; var type = context.ModelType; var jsonSerializer = CreateJsonSerializer(); jsonSerializer.Error += errorHandler; object model; try { model = jsonSerializer.Deserialize(jsonReader, type); } finally { // Clean up the error handler in case CreateJsonSerializer() reuses a serializer jsonSerializer.Error -= errorHandler; } if (successful) { return(InputFormatterResult.SuccessAsync(model)); } return(InputFormatterResult.FailureAsync()); } } }
public override Task <InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { throw new NotImplementedException(); }
/// <inheritdoc /> public async override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var result = await base.ReadRequestBodyAsync(context); if (!result.HasError) { var jsonPatchDocument = (IJsonPatchDocument)result.Model; if (jsonPatchDocument != null && SerializerSettings.ContractResolver != null) { jsonPatchDocument.ContractResolver = SerializerSettings.ContractResolver; } } return result; }