| File: ModelBinding\Binders\DateTimeModelBinder.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable enable using System.Globalization; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders; /// <summary> /// An <see cref="IModelBinder"/> for <see cref="DateTime"/> and nullable <see cref="DateTime"/> models. /// </summary> public class DateTimeModelBinder : IModelBinder { private readonly DateTimeStyles _supportedStyles; private readonly ILogger _logger; /// <summary> /// Initializes a new instance of <see cref="DateTimeModelBinder"/>. /// </summary> /// <param name="supportedStyles">The <see cref="DateTimeStyles"/>.</param> /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param> public DateTimeModelBinder(DateTimeStyles supportedStyles, ILoggerFactory loggerFactory) { ArgumentNullException.ThrowIfNull(loggerFactory); _supportedStyles = supportedStyles; _logger = loggerFactory.CreateLogger(typeof(DateTimeModelBinder)); } /// <inheritdoc /> public Task BindModelAsync(ModelBindingContext bindingContext) { ArgumentNullException.ThrowIfNull(bindingContext); _logger.AttemptingToBindModel(bindingContext); var modelName = bindingContext.ModelName; var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); if (valueProviderResult == ValueProviderResult.None) { _logger.FoundNoValueInRequest(bindingContext); // no entry _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } var modelState = bindingContext.ModelState; modelState.SetModelValue(modelName, valueProviderResult); var metadata = bindingContext.ModelMetadata; var type = metadata.UnderlyingOrModelType; try { var value = valueProviderResult.FirstValue; object? model; if (string.IsNullOrWhiteSpace(value)) { // Parse() method trims the value (with common DateTimeSyles) then throws if the result is empty. model = null; } else if (type == typeof(DateTime)) { model = DateTime.Parse(value, valueProviderResult.Culture, _supportedStyles); } else { throw new NotSupportedException(); } // When converting value, a null model may indicate a failed conversion for an otherwise required // model (can't set a ValueType to null). This detects if a null model value is acceptable given the // current bindingContext. If not, an error is logged. if (model == null && !metadata.IsReferenceOrNullableType) { modelState.TryAddModelError( modelName, metadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor( valueProviderResult.ToString())); } else { bindingContext.Result = ModelBindingResult.Success(model); } } catch (Exception exception) { // Conversion failed. modelState.TryAddModelError(modelName, exception, metadata); } _logger.DoneAttemptingToBindModel(bindingContext); return Task.CompletedTask; } }