// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.TestHost; using ModelBindingWebSite; using Newtonsoft.Json; using Xunit; namespace Microsoft.AspNet.Mvc.FunctionalTests { public class ModelBindingTests { private readonly IServiceProvider _services = TestHelper.CreateServices("ModelBindingWebSite"); private readonly Action _app = new ModelBindingWebSite.Startup().Configure; [Theory] [InlineData("RestrictValueProvidersUsingFromRoute", "valueFromRoute")] [InlineData("RestrictValueProvidersUsingFromQuery", "valueFromQuery")] [InlineData("RestrictValueProvidersUsingFromForm", "valueFromForm")] public async Task CompositeModelBinder_Restricts_ValueProviders(string actionName, string expectedValue) { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Provide all three values, it should bind based on the attribute on the action method. var request = new HttpRequestMessage(HttpMethod.Post, string.Format("http://localhost/CompositeTest/{0}/valueFromRoute?param=valueFromQuery", actionName)); var nameValueCollection = new List> { new KeyValuePair("param", "valueFromForm"), }; request.Content = new FormUrlEncodedContent(nameValueCollection); // Act var response = await client.SendAsync(request); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(expectedValue, await response.Content.ReadAsStringAsync()); } [Fact] public async Task MultipleParametersMarkedWithFromBody_Throws() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act & Assert var ex = await Assert.ThrowsAsync(() => client.GetAsync("http://localhost/MultipleParametersFromBody/MultipleParametersFromBodyThrows")); Assert.Equal("More than one parameter is bound to the HTTP request's content.", ex.Message); } [Fact] public async Task ParametersWithNoMarkersUseTheAvailableValueProviders() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetAsync("http://localhost/WithMarker" + "/ParametersWithNoMarkersUseTheAvailableValueProviders" + "?Name=somename&Age=12"); //Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var emp = JsonConvert.DeserializeObject( await response.Content.ReadAsStringAsync()); Assert.Null(emp.Department); Assert.Equal("somename", emp.Name); Assert.Equal(12, emp.Age); } [Fact] public async Task ParametersAreAlwaysCreated() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetAsync("http://localhost/WithoutMarker" + "/GetPersonParameter" + "?Name=somename&Age=12"); //Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var person = JsonConvert.DeserializeObject( await response.Content.ReadAsStringAsync()); Assert.NotNull(person); Assert.Equal("somename", person.Name); Assert.Equal(12, person.Age); } [Fact] public async Task ModelBindCancellationTokenParameteres() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetAsync("http://localhost/Home/ActionWithCancellationToken"); //Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("true", await response.Content.ReadAsStringAsync()); } [Fact] public async Task ModelBindCancellationToken_ForProperties() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetAsync( "http://localhost/Home/ActionWithCancellationTokenModel?wrapper=bogusValue"); //Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("true", await response.Content.ReadAsStringAsync()); } [Fact] public async Task ModelBindingBindsBase64StringsToByteArrays() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetAsync("http://localhost/Home/Index?byteValues=SGVsbG9Xb3JsZA=="); //Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("HelloWorld", await response.Content.ReadAsStringAsync()); } [Fact] public async Task ModelBindingBindsEmptyStringsToByteArrays() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetAsync("http://localhost/Home/Index?byteValues="); //Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("\0", await response.Content.ReadAsStringAsync()); } [Fact] public async Task ModelBinding_LimitsErrorsToMaxErrorCount() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); var queryString = string.Join("=&", Enumerable.Range(0, 10).Select(i => "field" + i)); // Act var response = await client.GetStringAsync("http://localhost/Home/ModelWithTooManyValidationErrors?" + queryString); //Assert var json = JsonConvert.DeserializeObject>(response); // 8 is the value of MaxModelValidationErrors for the application being tested. Assert.Equal(8, json.Count); Assert.Equal("The Field1 field is required.", json["Field1.Field1"]); Assert.Equal("The Field2 field is required.", json["Field1.Field2"]); Assert.Equal("The Field3 field is required.", json["Field1.Field3"]); Assert.Equal("The Field1 field is required.", json["Field2.Field1"]); Assert.Equal("The Field2 field is required.", json["Field2.Field2"]); Assert.Equal("The Field3 field is required.", json["Field2.Field3"]); Assert.Equal("The Field1 field is required.", json["Field3.Field1"]); Assert.Equal("The maximum number of allowed model errors has been reached.", json[""]); } [Fact] public async Task ModelBinding_ValidatesAllPropertiesInModel() { // Arrange var server = TestServer.Create(_services, _app); var client = server.CreateClient(); // Act var response = await client.GetStringAsync("http://localhost/Home/ModelWithFewValidationErrors?model="); //Assert var json = JsonConvert.DeserializeObject>(response); Assert.Equal(3, json.Count); Assert.Equal("The Field1 field is required.", json["model.Field1"]); Assert.Equal("The Field2 field is required.", json["model.Field2"]); Assert.Equal("The Field3 field is required.", json["model.Field3"]); } } }