Add fields bindings

This commit is contained in:
Zoe Roux 2023-10-27 20:35:35 +02:00
parent d3fbec1a9d
commit c7db07f7ba
3 changed files with 75 additions and 14 deletions

View File

@ -16,33 +16,33 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>. // along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection; using System.Reflection;
using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo.Abstractions.Models.Utils; namespace Kyoo.Abstractions.Models.Utils;
public class Include<T> public class Include<T>
where T : IResource
{ {
public string[] Fields { get; private init; } public ICollection<string> Fields { get; private init; } = ArraySegment<string>.Empty;
public static Include<T> From(string fields) public static Include<T> From(string? fields)
{ {
if (string.IsNullOrEmpty(fields)) if (string.IsNullOrEmpty(fields))
return new(); return new Include<T>();
string[] values = fields.Split(','); return new Include<T>
foreach (string field in values)
{ {
PropertyInfo? prop = typeof(T).GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); Fields = fields.Split(',').Select(x =>
{
PropertyInfo? prop = typeof(T).GetProperty(x, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (prop?.GetCustomAttribute<LoadableRelationAttribute>() == null) if (prop?.GetCustomAttribute<LoadableRelationAttribute>() == null)
throw new ValidationException($"No loadable relation with the name {field}."); throw new ValidationException($"No loadable relation with the name {x}.");
} return prop.Name;
}).ToArray()
return new()
{
Fields = values,
}; };
} }
} }

View File

@ -71,6 +71,7 @@ namespace Kyoo.Core
{ {
options.Filters.Add<ExceptionFilter>(); options.Filters.Add<ExceptionFilter>();
options.ModelBinderProviders.Insert(0, new SortBinder.Provider()); options.ModelBinderProviders.Insert(0, new SortBinder.Provider());
options.ModelBinderProviders.Insert(0, new IncludeBinder.Provider());
}) })
.AddNewtonsoftJson(x => .AddNewtonsoftJson(x =>
{ {

View File

@ -0,0 +1,60 @@
// Kyoo - A portable and vast media library solution.
// Copyright (c) Kyoo.
//
// See AUTHORS.md and LICENSE file in the project root for full license information.
//
// Kyoo is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// Kyoo is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Reflection;
using System.Threading.Tasks;
using Kyoo.Abstractions.Models.Utils;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
namespace Kyoo.Core.Api;
public class IncludeBinder : IModelBinder
{
private readonly Random _rng = new();
public Task BindModelAsync(ModelBindingContext bindingContext)
{
ValueProviderResult fields = bindingContext.ValueProvider.GetValue(bindingContext.FieldName);
try
{
object include = bindingContext.ModelType.GetMethod(nameof(Include<object>.From))!
.Invoke(null, new object?[] { fields.FirstValue })!;
bindingContext.Result = ModelBindingResult.Success(include);
return Task.CompletedTask;
}
catch (TargetInvocationException ex)
{
throw ex.InnerException!;
}
}
public class Provider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType.Name == "Include`1")
{
return new BinderTypeModelBinder(typeof(IncludeBinder));
}
return null!;
}
}
}