From 56a5eb9677644c29d79a891ba483ec3f5beb7ef7 Mon Sep 17 00:00:00 2001 From: DmitriyKulagin Date: Tue, 9 Aug 2022 11:35:02 +0300 Subject: [PATCH] #6361 Fixed model bindind for BaseNopModel.CustomProperties[Obsolete] --- .../Extensions/ServiceCollectionExtensions.cs | 1 + .../Nop.Web.Framework/Models/BaseNopModel.cs | 5 +- .../Binders/CustomPropertiesModelBinder.cs | 58 +++++++++++++++++++ .../CustomPropertiesModelBinderProvider.cs | 26 +++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinder.cs create mode 100644 src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinderProvider.cs diff --git a/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ServiceCollectionExtensions.cs b/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ServiceCollectionExtensions.cs index 3b90280dd25..26371172391 100644 --- a/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ServiceCollectionExtensions.cs +++ b/src/Presentation/Nop.Web.Framework/Infrastructure/Extensions/ServiceCollectionExtensions.cs @@ -296,6 +296,7 @@ public static IMvcBuilder AddNopMvc(this IServiceCollection services) { //we'll use this until https://github.com/dotnet/aspnetcore/issues/6566 is solved options.ModelBinderProviders.Insert(0, new InvariantNumberModelBinderProvider()); + options.ModelBinderProviders.Insert(1, new CustomPropertiesModelBinderProvider()); //add custom display metadata provider options.ModelMetadataDetailsProviders.Add(new NopMetadataProvider()); diff --git a/src/Presentation/Nop.Web.Framework/Models/BaseNopModel.cs b/src/Presentation/Nop.Web.Framework/Models/BaseNopModel.cs index 9fa9a05903a..9f688b7ccd2 100644 --- a/src/Presentation/Nop.Web.Framework/Models/BaseNopModel.cs +++ b/src/Presentation/Nop.Web.Framework/Models/BaseNopModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Xml.Serialization; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -14,6 +15,7 @@ public partial record BaseNopModel /// /// Ctor /// + [Obsolete] public BaseNopModel() { CustomProperties = new Dictionary(); @@ -53,6 +55,7 @@ protected virtual void PostInitialize() /// Gets or sets property to store any custom values for models /// [XmlIgnore] + [Obsolete] public Dictionary CustomProperties { get; set; } #endregion diff --git a/src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinder.cs b/src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinder.cs new file mode 100644 index 00000000000..70bc61463f9 --- /dev/null +++ b/src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinder.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Nop.Web.Framework.Mvc.ModelBinding.Binders +{ + /// + /// Represents model binder for CustomProperties + /// + [Obsolete] + public class CustomPropertiesModelBinder : IModelBinder + { + Task IModelBinder.BindModelAsync(ModelBindingContext bindingContext) + { + if (bindingContext == null) + throw new ArgumentNullException(nameof(bindingContext)); + + var modelName = bindingContext.ModelName; + + var result = new Dictionary(); + if (bindingContext.HttpContext.Request.Method == "POST") + { + var keys = bindingContext.HttpContext.Request.Form.Keys.ToList().Where(x => x.IndexOf(modelName) == 0); + + if (keys != null && keys.Any()) + { + foreach (var key in keys) + { + var dicKey = key.Replace(modelName + "[", "").Replace("]", ""); + bindingContext.HttpContext.Request.Form.TryGetValue(key, out var value); + result.Add(dicKey, value.ToString()); + } + } + } + if (bindingContext.HttpContext.Request.Method == "GET") + { + var keys = bindingContext.HttpContext.Request.QueryString.Value.Split('&').Where(x => x.StartsWith(modelName)); + + if (keys != null && keys.Any()) + { + foreach (var key in keys) + { + var dicKey = key[(key.IndexOf("[") + 1)..key.IndexOf("]")]; + var value = key[(key.IndexOf("=") + 1)..]; + + result.Add(dicKey, value); + } + } + } + bindingContext.Result = ModelBindingResult.Success(result); + + return Task.CompletedTask; + + } + } +} diff --git a/src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinderProvider.cs b/src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinderProvider.cs new file mode 100644 index 00000000000..1b4d1007709 --- /dev/null +++ b/src/Presentation/Nop.Web.Framework/Mvc/ModelBinding/Binders/CustomPropertiesModelBinderProvider.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Nop.Web.Framework.Models; + +namespace Nop.Web.Framework.Mvc.ModelBinding.Binders +{ + /// + /// Represents a model binder provider for CustomProperties + /// + [Obsolete] + public class CustomPropertiesModelBinderProvider : IModelBinderProvider + { + IModelBinder IModelBinderProvider.GetBinder(ModelBinderProviderContext context) + { + var propertyBinders = context.Metadata.Properties + .ToDictionary(modelProperty => modelProperty, modelProperty => context.CreateBinder(modelProperty)); + + if (context.Metadata.ModelType == typeof(Dictionary) && context.Metadata.PropertyName == nameof(BaseNopModel.CustomProperties)) + return new CustomPropertiesModelBinder(); + else + return null; + } + } +}