8#if NETSTANDARD2_0 || NET5_0_OR_GREATER || NETCOREAPP3_1
10using System.Collections;
12using System.Threading.Tasks;
13using Microsoft.AspNetCore.Mvc.ModelBinding;
21 public class CslaModelBinder : Server.ObjectFactory, IModelBinder
33 public Task BindModelAsync(ModelBindingContext bindingContext)
35 ApplicationContext = (ApplicationContext)bindingContext.HttpContext.RequestServices.GetService(typeof(ApplicationContext));
36 if (bindingContext ==
null)
38 throw new ArgumentNullException(nameof(bindingContext));
41 bindingContext.Result = ModelBindingResult.Failed();
42 var result = ApplicationContext.CreateInstanceDI(bindingContext.ModelType);
45 if (typeof(Core.IEditableCollection).IsAssignableFrom(bindingContext.ModelType))
47 BindBusinessListBase(bindingContext, result);
48 bindingContext.Result = ModelBindingResult.Success(result);
50 else if (typeof(Core.IEditableBusinessObject).IsAssignableFrom(bindingContext.ModelType))
52 BindBusinessBase(bindingContext, result);
53 bindingContext.Result = ModelBindingResult.Success(result);
56 return Task.CompletedTask;
59 private void BindBusinessBase(ModelBindingContext bindingContext,
object result)
61 var properties = Core.FieldManager.PropertyInfoManager.GetRegisteredProperties(bindingContext.ModelType);
62 foreach (var item
in properties)
65 if (
string.IsNullOrEmpty(bindingContext.ModelName))
66 index = $
"{item.Name}";
68 index = $
"{bindingContext.ModelName}.{item.Name}";
69 BindSingleProperty(bindingContext, result, item, index);
74 private void BindBusinessListBase(ModelBindingContext bindingContext,
object result)
76 var applicationContext = (ApplicationContext)bindingContext.HttpContext.RequestServices.GetService(typeof(ApplicationContext));
77 var formKeys = bindingContext.ActionContext.HttpContext.Request.Form.Keys.Where(_ => _.StartsWith(bindingContext.ModelName));
78 var childType = Utilities.GetChildItemType(bindingContext.ModelType);
79 var properties = Core.FieldManager.PropertyInfoManager.GetRegisteredProperties(childType);
80 var list = (IList)result;
82 var itemCount = formKeys.Count() / properties.Count();
83 for (
int i = 0; i < itemCount; i++)
85 var child = applicationContext.CreateInstanceDI(childType);
88 throw new InvalidOperationException($
"Could not create instance of child type {childType}");
89 foreach (var item
in properties)
91 var index = $
"{bindingContext.ModelName}[{i}].{item.Name}";
92 BindSingleProperty(bindingContext, child, item, index);
95 if (!list.Contains(child))
100 private void BindSingleProperty(ModelBindingContext bindingContext,
object result, Core.IPropertyInfo item,
string index)
104 var value = bindingContext.ActionContext.HttpContext.Request.Form[index].FirstOrDefault();
107 if (item.Type.Equals(typeof(
string)))
108 Reflection.MethodCaller.CallPropertySetter(result, item.Name, value);
109 else if (value !=
null)
110 Reflection.MethodCaller.CallPropertySetter(result, item.Name, Utilities.CoerceValue(item.Type, value.GetType(),
null, value));
112 Reflection.MethodCaller.CallPropertySetter(result, item.Name,
null);
116 if (item.Type.Equals(typeof(
string)))
117 LoadProperty(result, item, value);
118 else if (value !=
null)
119 LoadProperty(result, item, Utilities.CoerceValue(item.Type, value.GetType(),
null, value));
121 LoadProperty(result, item,
null);
126 throw new Exception($
"Could not map {index} to model", ex);
133using System.Collections.Generic;
136using System.ComponentModel;
137using System.Collections;
147 private bool _checkRulesOnModelUpdated;
155 _checkRulesOnModelUpdated = CheckRulesOnModelUpdated;
164 public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
166 if (typeof(Core.IEditableCollection).IsAssignableFrom((bindingContext.ModelType)))
167 return BindCslaCollection(controllerContext, bindingContext);
169 var suppress = bindingContext.Model as Core.ICheckRules;
170 if (suppress !=
null)
171 suppress.SuppressRuleChecking();
172 var result = base.BindModel(controllerContext, bindingContext);
182 private object BindCslaCollection(ControllerContext controllerContext, ModelBindingContext bindingContext)
184 if (bindingContext.Model ==
null)
185 bindingContext.ModelMetadata.Model =
CreateModel(controllerContext, bindingContext, bindingContext.ModelType);
187 var collection = (IList)bindingContext.Model;
188 for (
int currIdx = 0; currIdx < collection.Count; currIdx++)
190 string subIndexKey = CreateSubIndexName(bindingContext.ModelName, currIdx);
191 if (!bindingContext.ValueProvider.ContainsPrefix(subIndexKey))
193 var elementModel = collection[currIdx];
194 var suppress = elementModel as Core.ICheckRules;
195 if (suppress !=
null)
196 suppress.SuppressRuleChecking();
197 var elementContext =
new ModelBindingContext()
199 ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => elementModel, elementModel.GetType()),
200 ModelName = subIndexKey,
201 ModelState = bindingContext.ModelState,
202 PropertyFilter = bindingContext.PropertyFilter,
203 ValueProvider = bindingContext.ValueProvider
206 if (OnModelUpdating(controllerContext, elementContext))
209 foreach (PropertyDescriptor property
in GetFilteredModelProperties(controllerContext, elementContext))
211 BindProperty(controllerContext, elementContext, property);
217 return bindingContext.Model;
227 protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
229 var controller = controllerContext.Controller as
IModelCreator;
230 if (controller !=
null)
233 return base.CreateModel(controllerContext, bindingContext, modelType);
242 protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
244 var obj = bindingContext.Model as Core.BusinessBase;
247 if (this._checkRulesOnModelUpdated)
249 var suppress = obj as Core.ICheckRules;
250 if (suppress !=
null)
252 suppress.ResumeRuleChecking();
253 suppress.CheckRules();
256 var errors = from r in obj.BrokenRulesCollection
257 where r.Severity == Rules.RuleSeverity.Error
259 foreach (var item
in errors)
262 string mskey = CreateSubPropertyName(bindingContext.ModelName, item.Property ??
string.Empty);
263 if (bindingContext.ModelState.TryGetValue(mskey, out state))
265 if (state.Errors.Where(e => e.ErrorMessage == item.Description).Any())
268 bindingContext.ModelState.AddModelError(mskey, item.Description);
270 else if (mskey ==
string.Empty)
271 bindingContext.ModelState.AddModelError(bindingContext.ModelName, item.Description);
276 base.OnModelUpdated(controllerContext, bindingContext);
287 protected override void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor,
object value)
289 if (!(bindingContext.Model is Core.BusinessBase))
290 base.OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, value);
Model binder for use with CSLA .NET editable business objects.
override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
Creates an instance of the model if the controller implements IModelCreator.
CslaModelBinder(bool CheckRulesOnModelUpdated=true)
Creates an instance of the model binder.
override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
Binds the model by using the specified controller context and binding context.
override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
Checks the validation rules for properties after the Model has been updated.
override void OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
Prevents IDataErrorInfo validation from operating against editable objects.
ASP.NET MVC model creator.
object CreateModel(Type modelType)
Creates a model object of the specified type.
Defines a CSLA .NET MVC viewmodel object.
@ CheckRules
Called from CheckRules