diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 7a60b0deb4..ec7b84ff60 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; +using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; @@ -74,7 +75,7 @@ namespace Jellyfin.Api.Controllers public ActionResult MarkPlayedItem( [FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId, - [FromQuery] DateTime? datePlayed) + [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) { var user = _userManager.GetUserById(userId); var session = RequestHelpers.GetSession(_sessionManager, _authContext, Request); diff --git a/Jellyfin.Api/ModelBinders/LegacyDateTimeModelBinder.cs b/Jellyfin.Api/ModelBinders/LegacyDateTimeModelBinder.cs new file mode 100644 index 0000000000..e1cb725f3e --- /dev/null +++ b/Jellyfin.Api/ModelBinders/LegacyDateTimeModelBinder.cs @@ -0,0 +1,49 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Api.ModelBinders +{ + /// + /// DateTime model binder. + /// + public class LegacyDateTimeModelBinder : IModelBinder + { + // Borrowed from the DateTimeModelBinderProvider + private const DateTimeStyles SupportedStyles = DateTimeStyles.AdjustToUniversal | DateTimeStyles.AllowWhiteSpaces; + private readonly DateTimeModelBinder _defaultModelBinder; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + public LegacyDateTimeModelBinder(ILoggerFactory loggerFactory) + { + _defaultModelBinder = new DateTimeModelBinder(SupportedStyles, loggerFactory); + } + + /// + public Task BindModelAsync(ModelBindingContext bindingContext) + { + var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); + if (valueProviderResult.Values.Count == 1) + { + var dateTimeString = valueProviderResult.FirstValue; + // Mark Played Item. + if (DateTime.TryParseExact(dateTimeString, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var dateTime)) + { + bindingContext.Result = ModelBindingResult.Success(dateTime); + } + else + { + return _defaultModelBinder.BindModelAsync(bindingContext); + } + } + + return Task.CompletedTask; + } + } +} diff --git a/Jellyfin.Api/TypeConverters/DateTimeTypeConverter.cs b/Jellyfin.Api/TypeConverters/DateTimeTypeConverter.cs deleted file mode 100644 index 315b473293..0000000000 --- a/Jellyfin.Api/TypeConverters/DateTimeTypeConverter.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.ComponentModel; -using System.Globalization; - -namespace Jellyfin.Api.TypeConverters -{ - /// - /// Custom datetime parser. - /// - public class DateTimeTypeConverter : TypeConverter - { - /// - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - if (sourceType == typeof(string)) - { - return true; - } - - return base.CanConvertFrom(context, sourceType); - } - - /// - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string dateString) - { - // Mark Played Item. - if (DateTime.TryParseExact(dateString, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var dateTime)) - { - return dateTime; - } - - // Get Activity Logs. - if (DateTime.TryParse(dateString, null, DateTimeStyles.RoundtripKind, out dateTime)) - { - return dateTime; - } - } - - return base.ConvertFrom(context, culture, value); - } - } -} diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 62ffe174cd..2a62339a63 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -1,8 +1,5 @@ -using System; -using System.ComponentModel; using System.Net.Http.Headers; using System.Net.Mime; -using Jellyfin.Api.TypeConverters; using Jellyfin.Server.Extensions; using Jellyfin.Server.Implementations; using Jellyfin.Server.Middleware; @@ -164,9 +161,6 @@ namespace Jellyfin.Server endpoints.MapHealthChecks("/health"); }); }); - - // Add type descriptor for legacy datetime parsing. - TypeDescriptor.AddAttributes(typeof(DateTime?), new TypeConverterAttribute(typeof(DateTimeTypeConverter))); } } }