| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 | using System;using System.Collections.Generic;using System.ComponentModel;using System.Threading.Tasks;using Microsoft.AspNetCore.Mvc.ModelBinding;using Microsoft.Extensions.Logging;namespace Jellyfin.Api.ModelBinders;/// <summary>/// Comma delimited array model binder./// Returns an empty array of specified type if there is no query parameter./// </summary>public class CommaDelimitedArrayModelBinder : IModelBinder{    private readonly ILogger<CommaDelimitedArrayModelBinder> _logger;    /// <summary>    /// Initializes a new instance of the <see cref="CommaDelimitedArrayModelBinder"/> class.    /// </summary>    /// <param name="logger">Instance of the <see cref="ILogger{CommaDelimitedArrayModelBinder}"/> interface.</param>    public CommaDelimitedArrayModelBinder(ILogger<CommaDelimitedArrayModelBinder> logger)    {        _logger = logger;    }    /// <inheritdoc/>    public Task BindModelAsync(ModelBindingContext bindingContext)    {        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);        var elementType = bindingContext.ModelType.GetElementType() ?? bindingContext.ModelType.GenericTypeArguments[0];        var converter = TypeDescriptor.GetConverter(elementType);        if (valueProviderResult.Length > 1)        {            var typedValues = GetParsedResult(valueProviderResult.Values, elementType, converter);            bindingContext.Result = ModelBindingResult.Success(typedValues);        }        else        {            var value = valueProviderResult.FirstValue;            if (value is not null)            {                var splitValues = value.Split(',', StringSplitOptions.RemoveEmptyEntries);                var typedValues = GetParsedResult(splitValues, elementType, converter);                bindingContext.Result = ModelBindingResult.Success(typedValues);            }            else            {                var emptyResult = Array.CreateInstance(elementType, 0);                bindingContext.Result = ModelBindingResult.Success(emptyResult);            }        }        return Task.CompletedTask;    }    private Array GetParsedResult(IReadOnlyList<string> values, Type elementType, TypeConverter converter)    {        var parsedValues = new object?[values.Count];        var convertedCount = 0;        for (var i = 0; i < values.Count; i++)        {            try            {                parsedValues[i] = converter.ConvertFromString(values[i].Trim());                convertedCount++;            }            catch (FormatException e)            {                _logger.LogDebug(e, "Error converting value.");            }        }        var typedValues = Array.CreateInstance(elementType, convertedCount);        var typedValueIndex = 0;        for (var i = 0; i < parsedValues.Length; i++)        {            if (parsedValues[i] is not null)            {                typedValues.SetValue(parsedValues[i], typedValueIndex);                typedValueIndex++;            }        }        return typedValues;    }}
 |