Composite desing pattern with UI tree editor MVC

55 Views Asked by At

Have any of you guys ever created an MVC RuleEngine UI editor with composite pattern in .NET Core?

How did you do that? I struggling with rendering that Tree and making it bindable to model for controller while trying to save changes to db in XML.

@edit

I've tried to make this Custom Model Binder but it doesnt work :P

public class CustomBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var modelType = bindingContext.ModelType;
        if (modelType.IsAbstract)
        {
            var modelName = bindingContext.ModelName;
            var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName + ".ClassName");

            if (valueProviderResult != ValueProviderResult.None)
            {
                var modelTypeName = valueProviderResult.FirstValue;
                var type = modelType.Assembly.GetTypes().SingleOrDefault(x => x.IsSubclassOf(modelType) && x.Name == modelTypeName);

                if (type != null)
                {
                    FilterRule instance = Activator.CreateInstance(type) as FilterRule;
                    bindingContext.Result = ModelBindingResult.Success(instance);
                }
                else
                {
                    bindingContext.Result = ModelBindingResult.Failed();
                }
            }
        }

        return Task.CompletedTask;
    }
}

Instance is created by activator but it isnt binded to a model prop obj. Any ideas?

@Edit2

This is how I registred Binder:

builder.Services.AddControllers(o =>
{
    o.ModelBinderProviders.Insert(0, new CustomModelBinderProvider());
});

This is my Controller Action:

    [HttpPost]
    public IActionResult Update(RuleModel model)
    {
        try
        {
            ruleService.Update(model);
            return View();
        }
        catch (Exception ex)
        {
            return StatusCode(500, ex);
        }
    }

This is RuleModel:

public class RuleModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        [NotMapped]
        public FilterRule FilterRule
        {
            get
            {
                if (!string.IsNullOrWhiteSpace(this.FilterRuleRaw))
                {

                    return HtmlHelpers.Deserialize<FilterRule>(this.FilterRuleRaw, typeof(BaseAbstractClass));
                }
                else
                    return null;
            }
            set 
            { 
                this.FilterRuleRaw = HtmlHelpers.Serialize(this.FilterRule, typeof(BaseAbstractClass)); 
            }
        }
        public string FilterRuleRaw { get; set; }
        [NotMapped]
        public List<EffectRule> EffectRule
        {
            get
            {
                if (!string.IsNullOrWhiteSpace(this.EffectRuleRaw))
                    return JsonConvert.DeserializeObject<List<EffectRule>>(this.EffectRuleRaw);
                else
                    return null;
            }
            set
            {
                this.EffectRuleRaw = JsonConvert.SerializeObject(this.EffectRule, typeof(BaseAbstractClass), Formatting.None, new JsonSerializerSettings());
            }
        }
        public string? EffectRuleRaw { get; set; }
        public bool IsEnabled { get; set; }
        public DateTime DateChanged { get; set; }
        public int RuleSetId { get; set; }
        public virtual RuleSetModel RuleSet { get; set; }
    }

Here you have my request body key value pairs:

[
    {
        "key": "Id",
        "value": "14"
    },
    {
        "key": "RuleSetId",
        "value": "9"
    },
    {
        "key": "Name",
        "value": "New Rule"
    },
    {
        "key": "Description",
        "value": "123"
    },
    {
        "key": "IsEnabled",
        "value": "true"
    },
    {
        "key": "FilterRule.ClassName",
        "value": "FilterRuleMethodLogicalAnd"
    },
    {
        "key": "__RequestVerificationToken",
        "value": "CfDJ8C7XVp-U3ThBoklDaiDPi9n3-Y8WpuXvSu52ewI-x0BJSHaoOn1aOhKKf2BfqSqbYLxVXqNESQcFUnzeIRgo5B2i2oTIteCZORnY8zoY6wR7l1Uimb-qO1uOtpUn13MfhUN5UOfuQ9J4PS0ETorLxeY"
    },
    {
        "key": "IsEnabled",
        "value": "false"
    }
]
0

There are 0 best solutions below