Search This Blog

Loading...

Thursday, July 14, 2016

Can I connect an XAF application to a custom data source (Web service, OData service, NoSQL database, etc.)?

My colleague Michael and I have recently worked on the article clarifying the currently supported data stores for XAF, because from time to time we receive questions like the one above. Even though this is a very basic information, it is still worth checking out even if you already have some XAF experience. Please let me know if there are any questions on this.


XAF is a framework designed to visualize and work with data represented as business or domain objects. The object-relational mapping (ORM) concept is very important here as in our framework you should not normally think of database tables, stored procedures (SP), SQL statements, but rather operate data in an object-oriented manner. Check out the Business Classes vs Database Tables article and information about Domain Driven Design (DDD) to get more inspirations. To access and manipulate objects, queries for all CRUD operations are performed dynamically based on view properties via the IObjectSpace API in a unified way. This design implies certain requirements to the XAF application data source, and makes it difficult to use an arbitrary data service or a specialized database in this role.

Currently, XAF supports the XPO  and Entity Framework ORM libraries out of the box with the help of the XPObjectSpace/XPObjectSpaceProvider  and EFObjectSpace/EFObjectSpaceProvider APIs respectively. They allow connecting an XAF application directly to relational databases supported by these libraries. See the Database Engines Supported by XPO and Entity Framework Data Providers articles for more details.

Also, starting with version 16.1, we introduced the XAF Mobile (CTP) Application Platform. It exposes the XAF application database via the standard OData V3 service that can be consumed by the XAF mobile client, as well as by any custom client you may want to create. Refer to the FAQ: New XAF HTML5/JavaScript mobile UI (CTP) article for more details.


If data from any custom data source (even NoSQL) needs to be used in some XAF views (not all, because otherwise ROI from using XAF can be low), without replacing the main XAF application data store, non-persistent or POCO objects can be used to represent this data with the help of theNonPersistentObjectSpace/NonPersistentObjectSpaceProvider  APIs.  Non-persistent data is usually not queried from a database using your ORM data model, and this can be extremely helpful for analysis and reporting data obtained from dynamic runtime calculations, stored procedures, arbitrary SQL queries or third-party services. Also, such a non-persistent POCO class may be required if you want to display a standard XAF List or Detail View with temporary data generated in code or loaded from a custom storage; or display an empty View (dialog) and then process the user input. Refer to examples in the "Business Model Design - Non-Persistent Objects" part of the Task-Based Help topic for more details. Alternatively, you can display and manipulate any custom data with the help of non-XAF forms or fully custom user controls embedded into standard XAF views as described at eXpressApp Framework > Concepts > UI Construction > Using a Custom Control that is not Integrated by Default.

How to reuse XAF Views and other standard module functionality in non-XAF apps

And one more update of the popular support topic, but quite advanced, though. Anyway, here we go:


Take special note that this is a specific and non-standard use-case scenario, which is not intentionally supported and tested by us internally. By default, many application modules rely on the XAF infrastructure and cannot be used outside it without special initialization or boilerplate code, which is usually created in the default XAF project templates created by the XAF Solution Wizard (see the YourSolutionName.Win/Program.xx orYourSolutionName.Web/Global.asax.xx files for more details). At the moment, most functionality of UI modules available to end-users is supposed to work in the client XAF WinForms, ASP.NET Web Forms and Mobile apps. For instance, you cannot have an arbitrary XAF DetailView embedded into your non-XAF ASP.NET MVC or WinForms app without much preparation (see the example below for more details) or at all with all the standard XAF functionality included.


Even though there are also non-visual XAF core components that can be reused in non-XAF apps with less effort (e.g., our security, audit and validation engines), they still require implementing custom-tailored solutions and a special initialization manually in your non-XAF app. Finally, since we do not test such scenarios internally, we do not guarantee normal operation of all XAF components in non-XAF apps. Depending on the module and target use scenario, there may be nuances and you must carefully test these scenarios or may probably be required to write additional code to get it working according to your business needs. For instance, since many standard modules (security, validation, reports, etc.) depend on the XafApplication.LoggedOn event or the activation of controllers for the main application window to perform their initialization, you may need to replicate the same circumstances in your non-XAF app if you want to make use of dependent functions. Also, if you're developing a Windows Forms app, it must be single-threaded (STA) by design, so you cannot easily invoke the standard XAF WinForms functionality in threads other than the main one. 


On the other hand, it is important to note that in a well-designed and structured application, it is also not difficult to separate and reuse the ORM data model or business classes, which are normally not tied to the visual or UI parts. Very often, it is the best practice to have a single common or shared class library for your persistent classes, which may not have any XAF dependencies. This way, to use persistent objects in non-XAF applications and services, it is sufficient to add a reference to this shared assembly and then follow  your ORM documentation (e.g., XPO) to learn more on how to set up database connection, create, query, delete persistent objects.

How to display the currently logged user name in the header bar near the Log Off Action on the Web

Here is another recent support thread update about personalizing your Web app:

To accomplish your task, consider one of the following solutions depending on your business requirements:

1. Default web template modification

Create a custom Default content template and add a new table cell with the following code to the markup (between cells containing the logo and header menu):
[ASPx]
... <td> <img src="Images/Logo.png" /> </td> <td class="width100"></td> <td><%= DevExpress.ExpressApp.SecuritySystem.CurrentUserName %></td> <td> <div id="xafHeaderMenu" class="xafHeaderMenu" style="float: right;"> ... </td> ...
2. Inherit from the standard HeaderMenuController class
Override its GetActionContainerCaption method (and optionally the GetActionContainerImageUrl method) as shown in our XCRM demo ("C:\Users\Public\Documents\DevExpress Demos 1X.X\Components\eXpressApp Framework\XCRM\CS\XCRM.Module.Web\CustomHeaderMenuController.cs").

Tracing - How to customize the eXpressAppFramework.log file generation and other aspects of the default tracer behavior

In this short post I wanted to highlight a functionality and APIs I think any application framework must provide out-of-the-box as it is vital for effective debugging and troubleshooting during development and further application maintenance - logging errors and other diagnostic information.

Even though for the majority of our framework users it is sufficient to deal with this logging system using the high-level interface without digging much into its implementation details (e.g., by looking into the auto-generated eXpressAppFramework.log file or checking emails with error details whose sending can be automated with our framework by application administrators), sometimes it is helpful to see what is "under the hood" to consider new capabilities or improvements for your business. 

That said, let me quote my recent update to the old https://www.devexpress.com/kb=Q304721 article (yes, we constandly update our support knowledge base and especially popular public threads with the latest info and solutions) and, hopefully, you will find this information helpful for the future:

Our tracing mechanism relies on the standard .NET Framework logging APIs from the System.Diagnostics and related namespaces. By default, we use the TextWriterTraceListener class that writes all application events into the eXpressAppFramework.log file by means of our helperDevExpress.Persistent.Base.Tracing class. The latter is technically a wrapper above the standard trace listeners . You can learn more on this from eXpressApp Framework > Concepts > Debugging and Error Handling > Log Files.

Monday, June 6, 2016

How to access derived (inherited) objects from OData Service

I want to quote a new KB article we created to more easily answer such user questions, especially due to the increased interest in OData in light of the recent arrival of the XAF mobile UI (CTP)

Scenario/Situation
"I created an XPO OData service (XpoDataServiceV3) based on my model, but when I try to query a collection of objects that are derived from another persistent object, the result set includes all objects inherited from the base class. Is it a bug? How can I get only derived objects?"

Explanation/Solution
"This behavior is caused by limited support for derived objects in the OData protocol, which doesn't expose derived classes as entity sets. To access derived objects or their properties, you have to include a type cast using the qualified object type name in the path constructed for a base class. For example, if you wish to get Person objects that are inherited from Party, use the following query:

http://localhost:56789/MyDataService.svc/Party/Person/



Please refer to Derived Entity Type section of the OData Advanced Tutorial and Addressing Derived Types section of the OData protocol documentation for more examples.

Note that this specificity is not related to XPO. If you create a WCF Data Service based on an Entity Framework model, it will behave in a similar manner in regard to derived entities."



And here is a real-life URL query I tested with the data service I created with our MainDemo app and the new Mobile project template:

http://localhost:51562/DataService.svc/DevExpress_Persistent_BaseImpl_Task/MainDemo_Module_BusinessObjects_DemoTask?$filter=Subject%20eq%20%27Task1%27


Again, take special note that this is however, NOT specific to XAF itself or DevExpress ORM OData Service in any way, but rather to the OData V3 protocol itself.