File: BindingSourceMetadataProviderIntegrationTest.cs
Web Access
Project: src\src\Mvc\test\Mvc.IntegrationTests\Microsoft.AspNetCore.Mvc.IntegrationTests.csproj (Microsoft.AspNetCore.Mvc.IntegrationTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Primitives;
 
namespace Microsoft.AspNetCore.Mvc.IntegrationTests;
 
public class BindingSourceMetadataProviderIntegrationTest
{
    [Fact]
    public async Task BindParameter_WithCancellationToken_BindingSourceSpecial()
    {
        // Arrange
        var options = new MvcOptions();
        var setup = new MvcCoreMvcOptionsSetup(new TestHttpRequestStreamReaderFactory());
 
        options.ModelBinderProviders.Insert(0, new CancellationTokenModelBinderProvider());
 
        setup.Configure(options);
 
        var parameterBinder = ModelBindingTestHelper.GetParameterBinder(options);
        var parameter = new ParameterDescriptor()
        {
            Name = "Parameter1",
            BindingInfo = new BindingInfo(),
            ParameterType = typeof(CancellationTokenBundle),
        };
 
        var testContext = ModelBindingTestHelper.GetTestContext(request =>
        {
            request.Form = new FormCollection(new Dictionary<string, StringValues>
            {
                    { "name", new[] { "Fred" } }
            });
        });
 
        var modelState = testContext.ModelState;
        var token = testContext.HttpContext.RequestAborted;
 
        // Act
        var modelBindingResult = await parameterBinder.BindModelAsync(parameter, testContext);
 
        // Assert
        // ModelBindingResult
        Assert.True(modelBindingResult.IsModelSet);
 
        // Model
        var boundPerson = Assert.IsType<CancellationTokenBundle>(modelBindingResult.Model);
        Assert.NotNull(boundPerson);
        Assert.Equal("Fred", boundPerson.Name);
        Assert.Equal(token, boundPerson.Token);
 
        // ModelState
        Assert.True(modelState.IsValid);
    }
 
    private class CancellationTokenBundle
    {
        public string Name { get; set; }
 
        public CancellationToken Token { get; set; }
    }
 
    [Fact]
    public async Task BindParameter_WithFormFile_BindingSourceFormFile()
    {
        // Arrange
        var options = new MvcOptions();
        var setup = new MvcCoreMvcOptionsSetup(new TestHttpRequestStreamReaderFactory());
 
        options.ModelBinderProviders.Insert(0, new FormFileModelBinderProvider());
 
        setup.Configure(options);
 
        var parameterBinder = ModelBindingTestHelper.GetParameterBinder(options);
        var parameter = new ParameterDescriptor()
        {
            Name = "Parameter1",
            BindingInfo = new BindingInfo(),
            ParameterType = typeof(FormFileBundle),
        };
 
        var data = "Some Data Is Better Than No Data.";
        var testContext = ModelBindingTestHelper.GetTestContext(
            request =>
            {
                request.QueryString = QueryString.Create("Name", "Fred");
                UpdateRequest(request, data, "File");
            });
 
        var modelState = testContext.ModelState;
 
        // Act
        var modelBindingResult = await parameterBinder.BindModelAsync(parameter, testContext);
 
        // Assert
        // ModelBindingResult
        Assert.True(modelBindingResult.IsModelSet);
 
        // Model
        var boundPerson = Assert.IsType<FormFileBundle>(modelBindingResult.Model);
        Assert.Equal("Fred", boundPerson.Name);
        Assert.Equal("text.txt", boundPerson.File.FileName);
 
        // ModelState
        Assert.True(modelState.IsValid);
    }
 
    private class FormFileBundle
    {
        public string Name { get; set; }
 
        public IFormFile File { get; set; }
    }
 
    private void UpdateRequest(HttpRequest request, string data, string name)
    {
        const string fileName = "text.txt";
        var fileCollection = new FormFileCollection();
        var formCollection = new FormCollection(new Dictionary<string, StringValues>(), fileCollection);
 
        request.Form = formCollection;
        request.ContentType = "multipart/form-data; boundary=----WebKitFormBoundarymx2fSWqWSd0OxQqq";
 
        if (string.IsNullOrEmpty(data) || string.IsNullOrEmpty(name))
        {
            // Leave the submission empty.
            return;
        }
 
        request.Headers["Content-Disposition"] = $"form-data; name={name}; filename={fileName}";
 
        var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(data));
        fileCollection.Add(new FormFile(memoryStream, 0, data.Length, name, fileName)
        {
            Headers = request.Headers
        });
    }
}