Simple ModelBinders and Simple ModelBinder Poco-2
Covers simple scenario for each model binder. Covers scenarios mixing a POCO model binder -> Simple Model binder. This contains tests for FormCollectionModelBinder BinderTypeBasedModelBinder TypeConverterModelBinder Remainging: TypeMatchModelBinder This also adds missing unit test for TypeMatchModelBinder as well.
This commit is contained in:
parent
95feb5a3ec
commit
3a3acde904
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||
{
|
||||
public class TypeMatchModelBinderTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task BindModel_InvalidValueProviderResult_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var bindingContext = GetBindingContext();
|
||||
bindingContext.ValueProvider = new SimpleHttpValueProvider
|
||||
{
|
||||
{ "theModelName", "not an integer" }
|
||||
};
|
||||
|
||||
var binder = new TypeMatchModelBinder();
|
||||
var modelState = bindingContext.ModelState;
|
||||
|
||||
// Act
|
||||
var result = await binder.BindModelAsync(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
Assert.Empty(modelState.Keys);
|
||||
Assert.True(modelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModel_ValidValueProviderResult_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var bindingContext = GetBindingContext();
|
||||
bindingContext.ValueProvider = new SimpleHttpValueProvider
|
||||
{
|
||||
{ "theModelName", 42 }
|
||||
};
|
||||
|
||||
var binder = new TypeMatchModelBinder();
|
||||
var modelState = bindingContext.ModelState;
|
||||
|
||||
// Act
|
||||
var result = await binder.BindModelAsync(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.True(result.IsModelSet);
|
||||
Assert.Equal(42, result.Model);
|
||||
var key = Assert.Single(modelState.Keys);
|
||||
Assert.Equal("theModelName", key);
|
||||
Assert.Equal("42", modelState[key].Value.AttemptedValue);
|
||||
Assert.Equal(42, modelState[key].Value.RawValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetCompatibleValueProviderResult_ValueProviderResultRawValueIncorrect_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var bindingContext = GetBindingContext();
|
||||
bindingContext.ValueProvider = new SimpleHttpValueProvider
|
||||
{
|
||||
{ "theModelName", "not an integer" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var vpResult = await TypeMatchModelBinder.GetCompatibleValueProviderResult(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(vpResult); // Raw value is the wrong type
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetCompatibleValueProviderResult_ValueProviderResultValid_ReturnsValueProviderResult()
|
||||
{
|
||||
// Arrange
|
||||
var bindingContext = GetBindingContext();
|
||||
bindingContext.ValueProvider = new SimpleHttpValueProvider
|
||||
{
|
||||
{ "theModelName", 42 }
|
||||
};
|
||||
|
||||
// Act
|
||||
var vpResult = await TypeMatchModelBinder.GetCompatibleValueProviderResult(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(vpResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetCompatibleValueProviderResult_ValueProviderReturnsNull_ReturnsNull()
|
||||
{
|
||||
// Arrange
|
||||
var bindingContext = GetBindingContext();
|
||||
bindingContext.ValueProvider = new SimpleHttpValueProvider();
|
||||
|
||||
// Act
|
||||
var vpResult = await TypeMatchModelBinder.GetCompatibleValueProviderResult(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(vpResult); // No key matched
|
||||
}
|
||||
|
||||
private static ModelBindingContext GetBindingContext()
|
||||
{
|
||||
return GetBindingContext(typeof(int));
|
||||
}
|
||||
|
||||
private static ModelBindingContext GetBindingContext(Type modelType)
|
||||
{
|
||||
return new ModelBindingContext
|
||||
{
|
||||
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType),
|
||||
ModelName = "theModelName"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class BinderTypeBasedModelBinderIntegrationTest
|
||||
{
|
||||
// The NullModelBinder and NullModelNotSetModelBinder return a non null ModelBindingResult but a null model.
|
||||
[Theory(Skip = "ModelBindingResult should be non null if a model binder returns a non null resul #2473.")]
|
||||
[InlineData(typeof(NullModelBinder), true)]
|
||||
[InlineData(typeof(NullModelNotSetModelBinder), false)]
|
||||
public async Task BindParameter_WithModelBinderType_NoData(Type modelBinderType, bool isModelSet)
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderType = modelBinderType
|
||||
},
|
||||
|
||||
ParameterType = typeof(string)
|
||||
};
|
||||
|
||||
// No data is passed.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => { });
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.Null(modelBindingResult.Model);
|
||||
Assert.Equal(isModelSet, modelBindingResult.IsModelSet);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
var key = Assert.Single(modelState.Keys);
|
||||
Assert.Equal("CustomParameter", key);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
Assert.Null(modelState[key].Value); // value is only set if the custom model binder sets it.
|
||||
}
|
||||
|
||||
private class Person2
|
||||
{
|
||||
}
|
||||
|
||||
// Since the NullResultModelBinder returns a null ModelBindingResult, it acts
|
||||
// as a non greedy model binder, however since it is applied using a BinderTypeBasedModelBinder,
|
||||
// which wraps this model binder and behaves as a greed model binder, we get a non null result.
|
||||
[Fact(Skip = "ModelBindingResult should be non null if a model binder returns a non null resul #2473.")]
|
||||
public async Task BindParameter_WithModelBinderType_NonGreedy_NoData()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderType = typeof(NullResultModelBinder)
|
||||
},
|
||||
|
||||
ParameterType = typeof(Person2)
|
||||
};
|
||||
|
||||
// No data is passed.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => { });
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState.Keys);
|
||||
}
|
||||
|
||||
// ModelBinderAttribute can be used without specifing the binder type.
|
||||
// In such cases BinderTypeBasedModelBinder acts like a non greedy binder where
|
||||
// it returns a null ModelBindingResult allowing other ModelBinders to run.
|
||||
[Fact]
|
||||
public async Task BindParameter_WithOutModelBinderType_NoData()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderType = typeof(NullResultModelBinder)
|
||||
},
|
||||
|
||||
ParameterType = typeof(Person2)
|
||||
};
|
||||
|
||||
// No data is passed.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => { });
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.Null(modelBindingResult);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState.Keys);
|
||||
}
|
||||
|
||||
// Ensures that prefix is part of the result returned back.
|
||||
[Fact]
|
||||
public async Task BindParameter_WithData_WithPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderType = typeof(SuccessModelBinder),
|
||||
BinderModelName = "CustomParameter"
|
||||
},
|
||||
|
||||
ParameterType = typeof(Person2)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => { });
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.Equal("Success", modelBindingResult.Model);
|
||||
Assert.Equal("CustomParameter", modelBindingResult.Key);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
var key = Assert.Single(modelState.Keys);
|
||||
Assert.Equal("CustomParameter", key);
|
||||
Assert.Null(modelState[key].Value); // value is only set if the custom model binder sets it.
|
||||
}
|
||||
|
||||
private class Person
|
||||
{
|
||||
public Address Address { get; set; }
|
||||
}
|
||||
|
||||
[ModelBinder(BinderType = typeof(AddressModelBinder))]
|
||||
private class Address
|
||||
{
|
||||
public string Street { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "Extra entries in model state #2446")]
|
||||
public async Task BindProperty_WithData_EmptyPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo(),
|
||||
ParameterType = typeof(Person)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => { });
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.Equal("Parameter1", modelBindingResult.Key);
|
||||
|
||||
// Model
|
||||
var boundPerson = Assert.IsType<Person>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson.Address);
|
||||
Assert.Equal("SomeStreet", boundPerson.Address.Street);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
// Should there be another key for what is there in the complex object ?
|
||||
// This should probably behave like body binder, where even the body gets validated by default.
|
||||
Assert.Equal(2, modelState.Keys.Count);
|
||||
var key = Assert.Single(modelState.Keys, k => k == "Parameter1.Address.Street");
|
||||
Assert.Null(modelState[key].Value); // value is only set if the custom model binder sets it.
|
||||
key = Assert.Single(modelState.Keys, k => k == "Parameter1.Address");
|
||||
Assert.Null(modelState[key].Value); // value is only set if the custom model binder sets it.
|
||||
}
|
||||
|
||||
[Fact(Skip = "Extra entries in model state #2446")]
|
||||
public async Task BindProperty_WithData_WithPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderModelName = "CustomParameter"
|
||||
},
|
||||
ParameterType = typeof(Person)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => { });
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.Equal("CustomParameter", modelBindingResult.Key);
|
||||
|
||||
// Model
|
||||
var boundPerson = Assert.IsType<Person>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson.Address);
|
||||
Assert.Equal("SomeStreet", boundPerson.Address.Street);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
// Should there be another key for what is there in the complex object ?
|
||||
// This should probably behave like body binder, where even the body gets validated by default.
|
||||
Assert.Equal(2, modelState.Keys.Count);
|
||||
var key = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Street");
|
||||
Assert.Null(modelState[key].Value); // value is only set if the custom model binder sets it.
|
||||
key = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address");
|
||||
Assert.Null(modelState[key].Value); // value is only set if the custom model binder sets it.
|
||||
}
|
||||
|
||||
private class AddressModelBinder : IModelBinder
|
||||
{
|
||||
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
|
||||
{
|
||||
if (bindingContext.ModelType != typeof(Address))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var address = new Address() { Street = "SomeStreet" };
|
||||
|
||||
return Task.FromResult(new ModelBindingResult(address, bindingContext.ModelName, true));
|
||||
}
|
||||
}
|
||||
|
||||
private class SuccessModelBinder : IModelBinder
|
||||
{
|
||||
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
|
||||
{
|
||||
return Task.FromResult(new ModelBindingResult("Success", bindingContext.ModelName, true));
|
||||
}
|
||||
}
|
||||
|
||||
private class NullModelBinder : IModelBinder
|
||||
{
|
||||
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
|
||||
{
|
||||
return Task.FromResult(new ModelBindingResult(null, bindingContext.ModelName, true));
|
||||
}
|
||||
}
|
||||
|
||||
private class NullModelNotSetModelBinder : IModelBinder
|
||||
{
|
||||
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
|
||||
{
|
||||
return Task.FromResult(new ModelBindingResult(null, bindingContext.ModelName, false));
|
||||
}
|
||||
}
|
||||
|
||||
private class NullResultModelBinder : IModelBinder
|
||||
{
|
||||
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
|
||||
{
|
||||
return Task.FromResult<ModelBindingResult>(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
// 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.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Collections;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class FormCollectionModelBindingIntegrationTest
|
||||
{
|
||||
private class Person
|
||||
{
|
||||
public Address Address { get; set; }
|
||||
}
|
||||
|
||||
private class Address
|
||||
{
|
||||
public int Zip { get; set; }
|
||||
|
||||
public FormCollection FileCollection { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445, Extra entries in model state #2446.")]
|
||||
public async Task BindProperty_WithData_WithEmptyPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo(),
|
||||
ParameterType = typeof(Person)
|
||||
};
|
||||
|
||||
var data = "Some Data Is Better Than No Data.";
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.QueryString = new QueryString("Address.Zip", "12345");
|
||||
UpdateRequest(request, data, "Address.File");
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
// Model
|
||||
var boundPerson = Assert.IsType<Person>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson.Address);
|
||||
var formCollection = Assert.IsAssignableFrom<FormCollection>(boundPerson.Address.FileCollection);
|
||||
var file = Assert.Single(formCollection.Files);
|
||||
Assert.Equal("form-data; name=Address.File; filename=text.txt", file.ContentDisposition);
|
||||
var reader = new StreamReader(file.OpenReadStream());
|
||||
Assert.Equal(data, reader.ReadToEnd());
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Equal(2, modelState.Count);
|
||||
Assert.Single(modelState.Keys, k => k == "Address.Zip");
|
||||
var key = Assert.Single(modelState.Keys, k => k == "Address.File"); // Should be only one key. bug #2446
|
||||
Assert.NotNull(modelState[key].Value); // should be non null bug #2445.
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Extra entries in model state #2446.")]
|
||||
public async Task BindParameter_WithData_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
// Setting a custom parameter prevents it from falling back to an empty prefix.
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(FormCollection)
|
||||
};
|
||||
|
||||
var data = "Some Data Is Better Than No Data.";
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
UpdateRequest(request, data, "CustomParameter");
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
// Model
|
||||
var formCollection = Assert.IsType<FormCollection>(modelBindingResult.Model);
|
||||
Assert.NotNull(formCollection);
|
||||
var file = Assert.Single(formCollection.Files);
|
||||
Assert.NotNull(file);
|
||||
Assert.Equal("form-data; name=CustomParameter; filename=text.txt", file.ContentDisposition);
|
||||
var reader = new StreamReader(file.OpenReadStream());
|
||||
Assert.Equal(data, reader.ReadToEnd());
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
// Validation should be skipped because we do not validate any parameters and since IFormFile is not
|
||||
// IValidatableObject, we should have no entries in the model state dictionary.
|
||||
Assert.Empty(modelState.Keys); // Enable when we fix #2446.
|
||||
}
|
||||
|
||||
[Fact(Skip = "Extra entries in model state #2446.")]
|
||||
public async Task BindParameter_NoData_DoesNotGetBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(FormCollection)
|
||||
};
|
||||
|
||||
// No data is passed.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.ContentType = "multipart/form-data";
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult); // Fails due to bug #2456
|
||||
Assert.Null(modelBindingResult.Model);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState.Keys);
|
||||
}
|
||||
|
||||
private void UpdateRequest(HttpRequest request, string data, string name)
|
||||
{
|
||||
var fileCollection = new FormFileCollection();
|
||||
var formCollection = new FormCollection(new Dictionary<string, string[]>(), fileCollection);
|
||||
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(data));
|
||||
|
||||
request.Form = formCollection;
|
||||
request.ContentType = "multipart/form-data";
|
||||
request.Headers["Content-Disposition"] = "form-data; name=" + name + "; filename=text.txt";
|
||||
fileCollection.Add(new FormFile(memoryStream, 0, data.Length)
|
||||
{
|
||||
Headers = request.Headers
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
{
|
||||
public class TypeConverterModelBinderIntegrationTest
|
||||
{
|
||||
private class Person
|
||||
{
|
||||
public Address Address { get; set; }
|
||||
}
|
||||
|
||||
private class Address
|
||||
{
|
||||
public int Zip { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "Extra entries in model state dictionary. #2466")]
|
||||
public async Task BindProperty_WithData_WithPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(Person)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("CustomParameter.Address.Zip", "1");
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
// Model
|
||||
var boundPerson = Assert.IsType<Person>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.NotNull(boundPerson.Address);
|
||||
Assert.Equal(1, boundPerson.Address.Zip);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
Assert.Equal(1, modelState.Keys.Count);
|
||||
var key = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Street");
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal("1", modelState[key].Value.AttemptedValue);
|
||||
Assert.Equal(1, modelState[key].Value.RawValue);
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Extra entries in model state dictionary. #2466")]
|
||||
public async Task BindProperty_WithData_WithEmptyPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo(),
|
||||
ParameterType = typeof(Person)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("Address.Zip", "1");
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
// Model
|
||||
var boundPerson = Assert.IsType<Person>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.NotNull(boundPerson.Address);
|
||||
Assert.Equal(1, boundPerson.Address.Zip);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
Assert.Equal(1, modelState.Keys.Count);
|
||||
var key = Assert.Single(modelState.Keys, k => k == "Address.Zip");
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal("1", modelState[key].Value.AttemptedValue);
|
||||
Assert.Equal(1, modelState[key].Value.RawValue);
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindParameter_WithData_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo(),
|
||||
|
||||
ParameterType = typeof(string)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("Parameter1", "someValue");
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
// Model
|
||||
var model = Assert.IsType<string>(modelBindingResult.Model);
|
||||
Assert.Equal("someValue", model);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
Assert.Equal(1, modelState.Keys.Count);
|
||||
var key = Assert.Single(modelState.Keys);
|
||||
Assert.Equal("Parameter1", key);
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal("someValue", modelState[key].Value.AttemptedValue);
|
||||
Assert.Equal("someValue", modelState[key].Value.RawValue);
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindParameter_NoData_DoesNotGetBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo(),
|
||||
|
||||
ParameterType = typeof(string)
|
||||
};
|
||||
|
||||
// No Data.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
// Assert
|
||||
|
||||
// ModelBindingResult
|
||||
Assert.Null(modelBindingResult);
|
||||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState.Keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"warningsAsErrors": "true"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Mvc":"6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc": "6.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestCommon": { "version": "6.0.0-*", "type": "build" },
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"Moq": "4.2.1312.1622",
|
||||
|
|
|
|||
Loading…
Reference in New Issue