Search This Blog

Loading...

Wednesday, January 21, 2015

Simplifying integration of custom controls bound to data from XAF application database - YOUR FEEDBACK IS NEEDED

Scenario


We are researching options to make it easier for our users to achieve the subject in the next version. One of the popular scenarios we were aware of from our users was integration of custom controls, often created in Visual Studio using the standard WinForms or ASP.NET WebForms approaches, and primarily designed for presenting data from the XAF application database in some very custom manner so that built-in XAF Property Editors  or List Editors were not good for this. For instance, you might want to show a list of records in a fancy grid with cards, image gallery or other controls or modes not integrated by default.



Current solutions and problems

XAF is very extensible framework and offers many ways of integrating custom or third party controls. We noticed that while doing so, feeding these custom controls with data from the application database was often a challenge for our users. This binding is done automatically for built-in forms and data editors, but requires writing some code that will read data via the IObjectSpace.GetObjects<T> method (to respect data security filters) and also listen to the IObjectSpace.Reloaded and other events to handle data updates. Finally, designing a data bound user control in Visual Studio often implies a direct connection to the database or using specialized data sources (e.g., to generate a list of grid columns or pivot fields), which do this for you. The latter forces you to think about obtaining an application connection string at design time, while this dynamic part is changed later in the most cases. Add to this different approaches for Entity Framework and XPO and you will get the whole picture.

New solutions (not yet built-in!)

Briefly, we decided to simplify this scenario. Here are two videos that shows one possible option:

ASP.NET:  http://www.screencast.com/t/OHhcHD9vy

WinForms: http://www.screencast.com/t/8M8K4eskkYO9

How it works?


In short, the proposed flow is as follows:

Beware of Windows update KB3025390 as it breaks EasyTest functionality in Internet Explorer 11

We were lucky enough to come across this issue when one day, almost all our internal functional tests (we use our in-house EasyTest engine) for XAF Web UI failed due to the following error:

    Type:       UnauthorizedAccessException
    Message:    Access is denied.

    Data:       0 entries
    Stack trace:

   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
   at System.Runtime.InteropServices.CustomMarshalers.ExpandoViewOfDispatchEx.DispExInvoke(String pstrMemberName, Int32 MemberDispID, Int32 Flags, Binder pBinder, Object[] aArgs, ParameterModifier[] aModifiers, CultureInfo pCultureInfo, String[] astrNamedParameters)
   at System.Runtime.InteropServices.CustomMarshalers.DispatchExMethodInfo.Invoke(Object pObj, BindingFlags invokeAttr, Binder pBinder, Object[] aParameters, CultureInfo pCulture)
   at System.Runtime.InteropServices.CustomMarshalers.DispatchExPropertyInfo.GetValue(Object pObj, BindingFlags invokeAttr, Binder binder, Object[] aIndex, CultureInfo culture)
   at System.Reflection.PropertyInfo.GetValue(Object obj, Object[] index)
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebCommandAdapter.<>c__DisplayClasse.<GetIReflectTestControlCore>b__9(Object obj)
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebCommandAdapter.ExecuteTimeoutFunction(Int32 timeoutMilliseconds, Int32 sleepTime, Predicate`1 predicate, Func`1 onTimeoutPredicate)
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebCommandAdapter.GetIReflectTestControlCore(String testControlsName, IHTMLDocument2 doc)
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebCommandAdapter.GetIReflectTestControl(String testControlsName, IHTMLDocument2 doc)
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebCommandAdapter.UpdateTestControls()
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebCommandAdapter.WaitForBrowserResponse(Boolean waitPostback, Boolean isSecondCall)
   at DevExpress.ExpressApp.EasyTest.WebAdapter.WebAdapter.CreateCommandAdapter()
   at DevExpress.EasyTest.Framework.TestExecutor.CreateCommandAdapterCore(IApplicationAdapter adapter)
   at DevExpress.EasyTest.Framework.TestExecutor.ExecuteCommands(IApplicationAdapter adapter, String& applicationName)
    InnerException is null

After several hours of researching and googling, we found out the Installation of KB3025390 breaks out-of-process JavaScript execution in IE11 ticket on MS Connect
as well as possible workarounds at https://code.google.com/p/selenium/issues/detail?id=8302

Thursday, January 8, 2015

Model.XAFML and storing XAF application UI settings in the database

As we are improving our newest "Persisting UI settings in the database" feature (quickly learn more about it from this video or blog), I wanted to pay your attention to the ModelDifferenceDbStore - Always take into account the latest changes made to the Model.XAFML file at design time ticket I created based on the users feedback. Let me quote myself from that thread:
Prerequisites

By default, starting with v14.2, all new XAF WinForms projects will store administrative (Model.XAFML) and user differences in the database tables (ModelDifference and ModelDifferenceAspect). 

This built-in option stems from the How to: Store Model Differences in Database example we had in the past.
This new behavior is plugged-in if the Security System is enabled in the Solution Wizard and is technically done by subscribing to the CreateCustomModelDifferenceStore and CreateCustomUserModelDifferenceStore events within YourSolutionName.Module.Win/Module.xx file. Refer to the eXpressApp Framework > Task-Based Help > How to: Store the Application Model Differences in the Database article for more details.

Problem description
As of v14.2.3, the contents of the Model.XAFML file are once read during the first application run and are stored in the database. Thus, any subsequent changes to the Model.XAFML file during development will not be re-read into the database or ignored. This feature request is for improving the developers' experience when this feature is in use.

Current solutions
Take special note that to start reading subsequent customizations from the Model.XAFML file at every application run as it was in the past, you will need to backup and then drop the existing ModelDifference and ModelDifferenceAspect tables in  your test database on your development machine.

Tuesday, December 30, 2014

About XAF Types Info Subsystem...

I have just closed the DC - Provide support for dynamic members in domain components ticket with two possible solutions (there were some specifics with regard to the late generation of real XPO classes for DC interfaces) and wanted to use this chance to draw your attention to some advanced stuff you may need one day - customizing your data model metadata at runtime via the underlying types info subsystem (ooohhh!)

In short, you may need customizations at this low level when you want to dynamically adjust your ORM data model mappings to the database, add or remove custom members for your data model at runtime (e.g., based on the info stored in the database, XML settings file or any other source) when implementing an app tailored to a specific client/user access rights, etc.

Leaving customizations aside (which is quite rare, to be honest), accessing information about the types (their metadata) registered within the XAF application is really common. For instance:

  • If you want to check what business class this View is for - check the View.ObjectTypeInfo property. 
  • If you want to check the member a PropertyEditor corresponds to - check its PropertyEditor.MemberInfo property.
  • Need to know whether a business class has a certain property? Use the ITypesInfo.FindMember or ITypeInfo.Members APIs.
  • Want to know which code attributes are applied to a class or property?  Call the IBaseInfo.FindAttributes method (check examples here).
  • Want to get/set a class property known only at runtime? Use the IMemberInfo.Get/SetValue methods (see an example in the end of this article - it's like .net reflection, but faster).


Our documentation describes this in several articles here:
eXpressApp Framework > Concepts > Business Model Design > Types Info Subsystem

I have also prepared a small schema to better explain the role this type of info subsystem plays:

As you can see from the schema, this 'types info subsystem' serves as a source for Application Model and thus UI generation. That said, in certain scenarios, you may want to access certain info at a higher level instead of accessing the types info subsystem directly.


If you are anxious to see more advanced XAF stuff today, consider reviewing my previous post at
How to customize the underlying database provider options and data access behavior in XAF.


See Also:
eXpressApp Framework > Concepts > Business Model Design > Data Types Supported by built-in Editors

Friday, December 26, 2014

A sporadic Visual Studio issue with the incorrect Action constructor after modifying Controller (Finally bypassed in 14.2.4!)

Have you ever seen a situation when your Actions defined in the Controller designer worked well, but one day they disappeared from the application UI and were no event present in the Application Model? Unfortunately, we sometimes did, and so did our customers under certain circumstances. The difficulty of this situation is that this annoying behavior in the IDE was truly random and sporadic, as it all might work on the same machine and then fail without any reason under the same circumstances, with no environment changes. This behavior could be reproducible with both new and existing Controllers and Actions. Our Controller/Action/designers code was fine and the same issue could be reproducible even with the standard Component Designer and standard MS components, so it was eventually reported to MS Connect:



This problem was not massive, to be honest, but the reports the report count reached a reasonable threshold within several years... 

Since we still continue to receive reports from our customers on this behavior from time to time, which negatively affects their experience with our product, we decided to introduce a special "hack" on our side, which helps avoid this behavior. This fix successfully worked in our tests with the problematic virtual machines where we happened to semi-stably isolate this strange behavior. This improvement is available starting with version 14.2.4 and I recommend you upgrade to this version if you experienced this behavior in the past.

Hopefully, you will never experience this again, and Happy XAFing/holidays!