/// <summary> /// Attempts to convert the values in <paramref name="result"/> to the specified type. /// </summary> /// <typeparam name="T">The <see cref="Type"/> for conversion.</typeparam> /// <param name="result">The <see cref="ValueProviderResult"/>.</param> /// <returns> /// The converted value, or the default value of <typeparamref name="T"/> if the value could not be converted. /// </returns> public static T ConvertTo <T>(this ValueProviderResult result) { object valueToConvert = null; if (result.Values.Count == 1) { valueToConvert = result.Values[0]; } else if (result.Values.Count > 1) { valueToConvert = result.Values.ToArray(); } return(ModelBindingHelper.ConvertTo <T>(valueToConvert, result.Culture)); }
/// <summary> /// Attempts to convert the values in <paramref name="result"/> to the specified type. /// </summary> /// <param name="result">The <see cref="ValueProviderResult"/>.</param> /// <param name="type">The <see cref="Type"/> for conversion.</param> /// <returns> /// The converted value, or the default value of <paramref name="type"/> if the value could not be converted. /// </returns> public static object ConvertTo(this ValueProviderResult result, Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } object valueToConvert = null; if (result.Values.Count == 1) { valueToConvert = result.Values[0]; } else if (result.Values.Count > 1) { valueToConvert = result.Values.ToArray(); } return(ModelBindingHelper.ConvertTo(valueToConvert, type, result.Culture)); }
/// <inheritdoc /> public override async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } await base.BindModelAsync(bindingContext); if (bindingContext.Result == null || !bindingContext.Result.Value.IsModelSet) { // No match for the prefix at all. return; } var result = bindingContext.Result.Value; Debug.Assert(result.Model != null); var model = (IDictionary <TKey, TValue>)result.Model; if (model.Count != 0) { // ICollection<KeyValuePair<TKey, TValue>> approach was successful. return; } var enumerableValueProvider = bindingContext.ValueProvider as IEnumerableValueProvider; if (enumerableValueProvider == null) { // No IEnumerableValueProvider available for the fallback approach. For example the user may have // replaced the ValueProvider with something other than a CompositeValueProvider. return; } // Attempt to bind dictionary from a set of prefix[key]=value entries. Get the short and long keys first. var keys = enumerableValueProvider.GetKeysFromPrefix(bindingContext.ModelName); if (!keys.Any()) { // No entries with the expected keys. return; } // Update the existing successful but empty ModelBindingResult. var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider; var valueMetadata = metadataProvider.GetMetadataForType(typeof(TValue)); var modelBinder = bindingContext.OperationBindingContext.ModelBinder; var keyMappings = new Dictionary <string, TKey>(StringComparer.Ordinal); foreach (var kvp in keys) { // Use InvariantCulture to convert the key since ExpressionHelper.GetExpressionText() would use // that culture when rendering a form. var convertedKey = ModelBindingHelper.ConvertTo <TKey>(kvp.Key, culture: null); using (bindingContext.EnterNestedScope( modelMetadata: valueMetadata, fieldName: bindingContext.FieldName, modelName: kvp.Value, model: null)) { await modelBinder.BindModelAsync(bindingContext); var valueResult = bindingContext.Result; // Always add an entry to the dictionary but validate only if binding was successful. model[convertedKey] = ModelBindingHelper.CastOrDefault <TValue>(valueResult.Value.Model); keyMappings.Add(kvp.Key, convertedKey); } } bindingContext.ValidationState.Add(model, new ValidationStateEntry() { Strategy = new ShortFormDictionaryValidationStrategy <TKey, TValue>(keyMappings, valueMetadata), }); }