Example #1
0
        /// <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);
        }
Example #3
0
        /// <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));
        }
Example #4
0
        /// <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);
        }
Example #10
0
 /// <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);
 }
Example #12
0
        /// <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;
        }
Example #13
0
        /// <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();
            }
        }
Example #14
0
        /// <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);
 }
Example #16
0
 /// <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);
            }
        }
Example #18
0
        /// <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());
                }
            }
        }
Example #19
0
 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;
        }