0

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"
    }
]
6
  • Where/how have you registered your CustomBinder?
    – Dai
    Commented Sep 23, 2023 at 12:51
  • Dai I've copied my code to post. Basicly I've created a dropdown list in form. That dropdown list contains List of subclasses of class FilterRule. Then in custom model binder I try to create an instance of which class name user choosed.
    – Zamash
    Commented Sep 23, 2023 at 13:04
  • That instance is created correctly but it still isnt binded to a FilterRule prop.
    – Zamash
    Commented Sep 23, 2023 at 13:06
  • Can you show us an example POST request body?
    – Dai
    Commented Sep 23, 2023 at 13:31
  • I have pasted pairs of keys and values to this post.
    – Zamash
    Commented Sep 23, 2023 at 15:12

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.