Scenario:
- A list of non-persistent objects should be shown in a dashboard, and one of the columns should contain a persistent object - T284048.
- It is necessary to assign an employee to several tasks. A user should select tasks, click a button, and a dialog with the selected tasks and the employees lookup should be shown - T179848.
- It is necessary to show a non-persistent popup dialog with a persistent Card lookup and a non-persistent CardElements list - T214493.
- It is necessary to show a dialog allowing you to select a persistent object in a lookup - see T362128, T106536.
Issues:
- It is necessary to load the initial values for referenced persistent objects. They cannot be loaded through the View's ObjectSpace, since NonPersistentObjectSpace cannot load persistent objects.
- Certain controllers may work incorrectly with persistent references, since NonPersistentObjectSpace provides unexpected information for them (e.g., it does not return a key value). As a reference, see Application.CreateCollectionSource and Application.CreateListView throws "type is non-persistent" when invoked on NonPersistentObjectSpace.
Current Solutions:
It is possible to implement simple solutions for each particular scenario and more complicated generic solutions here. For instance, in scenario #4, you can consider using the approach from the How to show a non-persistent class DetailView and filter related persistent lookup editors dynamically article, which relies on a persistent IObjectSpace and an orphan non-persistent class instantiated without any parameters. If necessary, you can always pass a required IObjectSpace object or other external data into this non-persistent class to implement a more complicated logic.
An example of a generic solution would be an attempt to implement a NonPersistentObjectSpace descendant that internally uses a persistent IObjectSpace instance for operations with persistent objects:
C#public class MixedObjectSpace : NonPersistentObjectSpace {
IObjectSpace persistentObjectSpace;
public MixedObjectSpace(ITypesInfo typesInfo, IObjectSpace persistentObjectSpace)
: base(typesInfo) {
this.persistentObjectSpace = persistentObjectSpace;
}
public MixedObjectSpace(ITypesInfo typesInfo, IEntityStore entityStore, IObjectSpace persistentObjectSpace)
: base(typesInfo, entityStore) {
this.persistentObjectSpace = persistentObjectSpace;
}
public override object GetKeyValue(object obj) {
Guard.ArgumentNotNull(obj, "obj");
if (persistentObjectSpace.CanInstantiate(obj.GetType())) {
return persistentObjectSpace.GetKeyValue(obj);
} else {
return base.GetKeyValue(obj);
}
}
public override string GetKeyValueAsString(object obj) {
Guard.ArgumentNotNull(obj, "obj");
if (persistentObjectSpace.CanInstantiate(obj.GetType())) {
return persistentObjectSpace.GetKeyValueAsString(obj);
} else {
return base.GetKeyValueAsString(obj);
}
}
public override object FindObject(Type objectType, DevExpress.Data.Filtering.CriteriaOperator criteria, bool inTransaction) {
if (persistentObjectSpace.CanInstantiate(objectType)) {
return persistentObjectSpace.FindObject(objectType, criteria, inTransaction);
} else {
return base.FindObject(objectType, criteria, inTransaction);
}
}
public override object CreateObject(Type type) {
if (persistentObjectSpace.CanInstantiate(type)) {
return persistentObjectSpace.CreateObject(type);
} else {
return base.CreateObject(type);
}
}
public override IList CreateCollection(Type objectType, CriteriaOperator criteria, IList<SortProperty> sorting) {
if (persistentObjectSpace.CanInstantiate(objectType)) {
return persistentObjectSpace.CreateCollection(objectType, criteria, sorting);
} else {
return base.CreateCollection(objectType, criteria, sorting);
}
}
public override object GetObjectKey(Type objectType, string objectKeyString) {
if (persistentObjectSpace.CanInstantiate(objectType)) {
return persistentObjectSpace.GetObjectKey(objectType, objectKeyString);
} else {
return base.GetObjectKey(objectType, objectKeyString);
}
}
public override object GetObjectByKey(Type type, object key) {
if (persistentObjectSpace.CanInstantiate(type)) {
return persistentObjectSpace.GetObjectByKey(type, key);
} else {
return base.GetObjectByKey(type, key);
}
}
...
}
public class MixedObjectSpaceProvider : NonPersistentObjectSpaceProvider, IObjectSpaceProvider {
private IObjectSpaceProvider persistentObjectSpaceProvider;
public MixedObjectSpaceProvider(ITypesInfo typesInfo, NonPersistentEntityStore entityStore, IObjectSpaceProvider persistentObjectSpaceProvider) : base(typesInfo, entityStore) {
this.persistentObjectSpaceProvider = persistentObjectSpaceProvider;
}
IObjectSpace IObjectSpaceProvider.CreateObjectSpace() {
return new MixedObjectSpace(TypesInfo, EntityStore, persistentObjectSpaceProvider.CreateObjectSpace());
}
}
Does this require different provider i registering code or will default one do?
args.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(TypesInfo, null));
Yes, if you do not create object spaces for non-persistent views manually, you will need to implement a custom provider:
public class MixedObjectSpaceProvider : NonPersistentObjectSpaceProvider, IObjectSpaceProvider { private IObjectSpaceProvider persistentObjectSpaceProvider; public MixedObjectSpaceProvider(ITypesInfo typesInfo, NonPersistentEntityStore entityStore, IObjectSpaceProvider persistentObjectSpaceProvider) : base(typesInfo, entityStore) { this.persistentObjectSpaceProvider = persistentObjectSpaceProvider; } IObjectSpace IObjectSpaceProvider.CreateObjectSpace() { return new MixedObjectSpace(TypesInfo, EntityStore, persistentObjectSpaceProvider.CreateObjectSpace()); } }
Ok, thanks.
Last question - is it possible to combine NonPersistentObjectSpaceProvider (for pure non-persistent objects) and MixedObjectSpaceProvider in one project?
I suppose not because ListView would not now which one to use. Is that correct?
Thanks,
Mario
This is possible - you can specify which provider should be used for certain types by passing these types to a provider's NonPersistentEntityStore. Here is an example:
winApplication.CreateCustomObjectSpaceProvider += (sender, e) => { e.ObjectSpaceProvider = new SecuredObjectSpaceProvider((ISelectDataSecurityProvider)winApplication.Security, e.ConnectionString, e.Connection, false); NonPersistentEntityStore store1 = new NonPersistentEntityStore((TypesInfo)winApplication.TypesInfo, new Type[] { typeof(MyNonPersistentObject) }.ToList<Type>()); NonPersistentEntityStore store2 = new NonPersistentEntityStore((TypesInfo)winApplication.TypesInfo, new Type[] { typeof(MyNonPersistentObject2) }.ToList<Type>()); e.ObjectSpaceProviders.Add(new NonPersistentObjectSpaceProvider(winApplication.TypesInfo, store1)); e.ObjectSpaceProviders.Add(new MixedObjectSpaceProvider(winApplication.TypesInfo, store2, e.ObjectSpaceProvider)); };
Ok, this is pretty cool :-)
Thanks.
I faced same problem but i cant find a way to resolve;
The error occurred:
Type: ArgumentNullException
Message: Değer null olamaz.
Parametre adı: objectKeyAsString
Data: 0 entries
Stack trace:
konum: DevExpress.Utils.Guard.ThrowArgumentNullException(String propName)
konum: DevExpress.Utils.Guard.ArgumentNotNull(Object value, String name)
konum: DevExpress.ExpressApp.Utils.Guard.ArgumentNotNull(Object argumentValue, String argumentName)
konum: DevExpress.ExpressApp.ObjectHandleHelper.CreateObjectHandle(ITypesInfo typesInfo, Type objectType, String objectKeyAsString)
konum: DevExpress.ExpressApp.BaseObjectSpace.GetObjectHandle(Object obj)
konum: DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.GetRequestHashCode(Type objectType, Object targetObject, String memberName, String operation, IObjectSpace clientObjectSpace)
konum: DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.IsGranted(Type objectType, Object targetObject, String memberName, String operation, IObjectSpace clientObjectSpace, Boolean& result)
konum: DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.DataManipulationRight_CustomHasPermissionTo(Object sender, CustomHasPermissionToEventArgs e)
konum: DevExpress.ExpressApp.SecuritySystem.IsGranted(IPermissionRequest permissionRequest)
konum: DevExpress.ExpressApp.DataManipulationRight.HasPermissionTo(Type objectType, String memberName, Object targetObject, IObjectSpace objectSpace, String operation)
konum: DevExpress.ExpressApp.DataManipulationRight.CanRead(Type objectType, String propertyName, Object targetObject, CollectionSourceBase collectionSource, IObjectSpace objectSpace)
konum: DevExpress.ExpressApp.SystemModule.ListViewControllerBase.CanRead(Object targetObject, String memberName, CollectionSourceBase collectionSource)
konum: DevExpress.ExpressApp.Web.SystemModule.ASPxGridListEditorMemberLevelSecurityController.Grid_CustomColumnDisplayText(Object sender, ASPxGridViewColumnDisplayTextEventArgs e)
konum: DevExpress.Web.ASPxGridViewColumnDisplayTextEventHandler.Invoke(Object sender, ASPxGridViewColumnDisplayTextEventArgs e)
konum: DevExpress.Web.ASPxGridView.RaiseCustomColumnDisplayText(ASPxGridColumnDisplayTextEventArgs e)
konum: DevExpress.Web.Internal.GridTextBuilder.GetDisplayControlArgsCore(IWebGridDataColumn column, Int32 visibleIndex, IValueProvider provider, ASPxGridBase grid, Object value)
konum: DevExpress.Web.Internal.GridTextBuilder.GetDisplayControlArgs(IWebGridDataColumn column, Int32 visibleIndex, IValueProvider provider, ASPxGridBase grid, Boolean highlightSearchText)
konum: DevExpress.Web.Internal.GridRenderHelper.CreateDataCellDisplayControl(IWebGridDataColumn column, Int32 visibleIndex, IValueProvider row)
konum: DevExpress.Web.Internal.GridRenderHelper.AddDisplayControlToDataCell(Control cell, IWebGridDataColumn column, Int32 visibleIndex, IValueProvider row)
konum: DevExpress.Web.Rendering.GridViewTableDataCell.CreateControlHierarchy()
konum: DevExpress.Web.Internal.InternalTableCell.CreateChildControls()
konum: System.Web.UI.Control.EnsureChildControls()
konum: DevExpress.Web.Internal.InternalTableCell.DevExpress.Web.Internal.IASPxWebControl.EnsureChildControls()
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Boolean skipContentContainers)
konum: DevExpress.Web.ASPxWebControlBase.EnsureChildControlsRecursive(Control control, Boolean skipContentContainers)
konum: DevExpress.Web.ASPxWebControlBase.EnsureChildControlsRecursive(Control control)
konum: DevExpress.Web.ASPxWebControlBase.CreateChildControls()
konum: System.Web.UI.Control.EnsureChildControls()
konum: DevExpress.Web.ASPxWebControlBase.EnsureChildControls()
konum: DevExpress.Web.ASPxWebControlBase.DevExpress.Web.Internal.IASPxWebControl.EnsureChildControls()
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Predicate`1 skipControlCondition)
konum: DevExpress.Web.Internal.RenderUtils.EnsureChildControlsRecursive(Control control, Boolean skipContentContainers)
konum: DevExpress.Web.ASPxWebControlBase.EnsureChildControlsRecursive(Control control, Boolean skipContentContainers)
konum: DevExpress.Web.ASPxWebControlBase.EnsureChildControlsRecursive(Control control)
konum: DevExpress.Web.ASPxWebControlBase.CreateChildControls()
konum: DevExpress.Web.ASPxWebControl.CreateChildControls()
konum: System.Web.UI.Control.EnsureChildControls()
konum: DevExpress.Web.ASPxWebControlBase.EnsureChildControls()
konum: DevExpress.Web.ASPxGridBase.Render(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
konum: System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
konum: System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer)
konum: System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
konum: System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
konum: System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer)
konum: System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
konum: System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
konum: System.Web.UI.Control.Render(HtmlTextWriter writer)
konum: System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter)
konum: System.Web.UI.Control.RenderControl(HtmlTextWriter writer)
konum: DevExpress.ExpressApp.Web.Templates.XafCallbackManager.GetCompactRenderResult(Control control)
konum: DevExpress.ExpressApp.Web.Templates.XafCallbackManager.GetControlChildrenRenderResult(Control control)
konum: DevExpress.ExpressApp.Web.Templates.XafCallbackManager.ProcessUpdatePanel(String cpControlsToUpdate, XafUpdatePanel updatePanel)
konum: DevExpress.ExpressApp.Web.Templates.XafCallbackManager.callbackControl_Callback(Object source, CallbackEventArgs e)
konum: DevExpress.Web.ASPxCallback.OnCallback(CallbackEventArgs e)
konum: DevExpress.Web.ASPxCallback.RaiseCallbackEvent(String eventArgument)
konum: DevExpress.Web.ASPxWebControl.System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent(String eventArgument)
InnerException is null
@Volkan: Please submit a separate ticket with a small debuggable sample reproducing this behavior so we can research it. Thanks.
Hi Dennis,
I found the problem. Problem occurs when the following code activated;
DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.Enable(DevExpress.ExpressApp.Security.Adapters.ReloadPermissionStrategy.OnLogon);
Hello Volkan,
To process your recent post more efficiently, I created a separate ticket on your behalf: T296849: ArgumentNullException can occur when DevExpress.ExpressApp.Security.Adapters.IsGrantedAdapter.Enable is used. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.