< Summary - Jellyfin

Information
Class: Jellyfin.Api.ModelBinders.CommaDelimitedArrayModelBinder
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
Line coverage
100%
Covered lines: 32
Uncovered lines: 0
Coverable lines: 32
Total lines: 89
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
BindModelAsync(...)100%66100%
GetParsedResult(...)100%66100%

File(s)

/srv/git/jellyfin/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel;
 4using System.Threading.Tasks;
 5using Microsoft.AspNetCore.Mvc.ModelBinding;
 6using Microsoft.Extensions.Logging;
 7
 8namespace Jellyfin.Api.ModelBinders;
 9
 10/// <summary>
 11/// Comma delimited array model binder.
 12/// Returns an empty array of specified type if there is no query parameter.
 13/// </summary>
 14public class CommaDelimitedArrayModelBinder : IModelBinder
 15{
 16    private readonly ILogger<CommaDelimitedArrayModelBinder> _logger;
 17
 18    /// <summary>
 19    /// Initializes a new instance of the <see cref="CommaDelimitedArrayModelBinder"/> class.
 20    /// </summary>
 21    /// <param name="logger">Instance of the <see cref="ILogger{CommaDelimitedArrayModelBinder}"/> interface.</param>
 22    public CommaDelimitedArrayModelBinder(ILogger<CommaDelimitedArrayModelBinder> logger)
 23    {
 13824        _logger = logger;
 13825    }
 26
 27    /// <inheritdoc/>
 28    public Task BindModelAsync(ModelBindingContext bindingContext)
 29    {
 13830        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
 13831        var elementType = bindingContext.ModelType.GetElementType() ?? bindingContext.ModelType.GenericTypeArguments[0];
 13832        var converter = TypeDescriptor.GetConverter(elementType);
 33
 13834        if (valueProviderResult.Length > 1)
 35        {
 236            var typedValues = GetParsedResult(valueProviderResult.Values, elementType, converter);
 237            bindingContext.Result = ModelBindingResult.Success(typedValues);
 38        }
 39        else
 40        {
 13641            var value = valueProviderResult.FirstValue;
 42
 13643            if (value is not null)
 44            {
 645                var splitValues = value.Split(',', StringSplitOptions.RemoveEmptyEntries);
 646                var typedValues = GetParsedResult(splitValues, elementType, converter);
 647                bindingContext.Result = ModelBindingResult.Success(typedValues);
 48            }
 49            else
 50            {
 13051                var emptyResult = Array.CreateInstance(elementType, 0);
 13052                bindingContext.Result = ModelBindingResult.Success(emptyResult);
 53            }
 54        }
 55
 13856        return Task.CompletedTask;
 57    }
 58
 59    private Array GetParsedResult(IReadOnlyList<string> values, Type elementType, TypeConverter converter)
 60    {
 861        var parsedValues = new object?[values.Count];
 862        var convertedCount = 0;
 4663        for (var i = 0; i < values.Count; i++)
 64        {
 65            try
 66            {
 1567                parsedValues[i] = converter.ConvertFromString(values[i].Trim());
 1268                convertedCount++;
 1269            }
 370            catch (FormatException e)
 71            {
 372                _logger.LogDebug(e, "Error converting value.");
 373            }
 74        }
 75
 876        var typedValues = Array.CreateInstance(elementType, convertedCount);
 877        var typedValueIndex = 0;
 4678        for (var i = 0; i < parsedValues.Length; i++)
 79        {
 1580            if (parsedValues[i] is not null)
 81            {
 1282                typedValues.SetValue(parsedValues[i], typedValueIndex);
 1283                typedValueIndex++;
 84            }
 85        }
 86
 887        return typedValues;
 88    }
 89}