Search This Blog

Showing posts with label advanced. Show all posts
Showing posts with label advanced. Show all posts

Tuesday, April 3, 2018

Old entries in the XPObjectType table - YOUR FEEDBACK IS NEEDED!


I am reviewing the priority of a quite dated SC item on the subject and wanted to ask the community for help. The problem may occur when old business class libraries exist in the application folder. By default, XPO tries to load them by the XPObjectType info along with the new versions. This may lead to a conflict at runtime or startup performance degradation. In the latter case, assembly type resolution may come at a cost (see the point 3.5 under How to measure and improve the application's performance).

Why are we hesitating to remove old XPObjectType entries by default?
1. Removing old XPObjectType records affects other apps accessing this database and is serious. Outdated service table records may relate to business class records too (inheritance mapping is in use very often). So, deleting them will lead to foreign key constraint violation. Creating a sophisticated generic solution for this is not easy task.

Monday, March 26, 2018

Integrating UnitOfWork and XPObjectSpace descendants into an XAF app


We've made some code changes for v17.2.6+ as well as created two articles for advanced XAF developers who may need the subject for some low-level tuning:





Sub-classing is itself easy.  The most interesting part comes for the two popular security configurations: the Integrated  mode and the Middle-Tier Application Server. Thankfully, this is rarely required for complex or specific scenarios only.  Here are several customer tickets for your reference:

    How to map a property to a calculated database column (implement a read-only persistent property)
    xpo and sql server identity fields
    Using inherited UnitOfWork object
    XAF: Create CreateCustomObjectSpaceProvider with parameters from login window
    SecurityStrategyComplex: How to modify objects/properties in code when the user does not have the permission?

To learn more about low-level options to control how your application saves data and where, check out the How to customize the underlying database provider options and data access behavior in XAF.

Your feedback is needed!
Finally, I am just curious: if you search your entire solution in Visual Studio (Control+Shift+F) for any of the ": UnitOfWork", ": XPObjectSpace", ": XPObjectSpaceProvider" strings or their VB.NET equivalents (e.g., Inherits UnitOfWork), how many occurrences  would you have and for what? Please let me know in the comments!

FreeImages.com/Terry Eaton

Monday, November 27, 2017

Welcome the DataStoreCreated event in the ConnectionDataStoreProvider and ConnectionStringDataStoreProvider classes

This is rather a minor improvement, but I bet it will save code lines for some advanced XAFers who touch the internals of the XPO data layer created by XAF for various low-level database-specific customization like setting connection timeouts, changing default schemas, enabling and customizing caching, service end-points, etc. Check out this updated article for some example code showing the new approach in action.
The DataStoreCreated  event is available in XAF v17.2+. Its event arguments (DataStoreCreatedEventArgs) expose the DataStore and Destination parameters that provide access to the current data store and its type (SchemaChecking,  Updating or Working).

Frankly speaking, this is quite low-level and rarely needed stuff, so we have not yet have it covered in the online docs, only in KBs. So, please refer to my 
How to customize the underlying database provider options and data access behavior in XAF article to learn more about it. Should you have any questions or additional usability suggestions, please let me know.

FreeImages/Chett Cole

Wednesday, October 25, 2017

Beware of the situation when a signed assembly with a business type used in the dashboard changes its version


I wanted to inform our Dashboard module users about a situation, which we missed originally:
DashboardObjectDataSource serializer fails to load a data source type when signed assemblies with a changed version are used

As you understand, it may occur only when target business types used in XML dashboard definitions with ObjectDataSource are from signed assemblies and the assembly version changes, e.g. when you deliver a new app version to the client:

 <DataSources>
    <ObjectDataSource ComponentName="dashboardObjectDataSource1">
      <Name>Object Data Source 1</Name>
      <DataSource Type="YourNamespace.YourObjectType, YourAssemblyName, Version=17.1.6498.1953, Culture=neutral, PublicKeyToken=YourPublicKeyToken" />
    </ObjectDataSource>
  </DataSources>



Currently, we recommend XAF application developers try a couple of solutions described in that thread, but they are not final solutions. We are currently reviewing them from the security point of view to make sure that the app won't be broken by passing another non-signed dll. For now, this does not seem to be the case, because business type information is obtained using the ReflectionHelper API from the already loaded assemblies, which are protected by the default .NET mechanisms. We just want to double-check or see if there are more suitable options. Ideally, I wish this to be working transparently for an application developer without the need to resolve any assemblies or types manually.


Your feedback is needed!

Have you experienced this behavior in your Dashboard apps? How do you currently cope with it? If there are existing solutions, share their details and also elaborate on their costs. Your feedback is greatly appreciated.


Wednesday, September 13, 2017

Simplifying the use of ASPxGridListEditor with XPO classes that have composite keys


Starting with the 17.1.4 version, you can use the built-in StructTypeConverter<T> for composite or compound key properties to enable some built-in DevExpress.Web.ASPxGridView functions in ASPxGridListEditor (e.g., inplace editing and the selection column), which would be missing without a type converter.


This converter can be applied to a struct (Structure in VB.NET) representing your complex key using the standard TypeConverterAttribute:

[TypeConverter(typeof(StructTypeConverter<CompoundKey>))]
public struct CompoundKey { ... }


You can view the full example by the documentation link above.


Despite this minor improvement making the lives of certain XAF users easier (and reducing our support costs too), I must emphasize that we do not recommend using composite keys in new apps. XPO supports such keys for legacy databases only and their use imposes some limitations on the default XAF functionality. You can learn more about this from How to create a persistent object for a database table with a compound key


FreeImages.Com/Kirill Levin

Monday, June 26, 2017

AuditTrail - How to show the change history for the current object in a separate form instead of a nested ListView

I wanted to draw your attention to the scenario and solution in our Support Center, which were found helpful by at least 4 other XAF customers using XPO for data access. As you know, by default, we offer our users a solution based on the nested ListView, which is automatically generated when you declare a collection property like this one:

    public XPCollection<AuditDataItemPersistent> AuditTrail {
        get {
            if(auditTrail == null) {
               auditTrail = AuditedObjectWeakReference.GetAuditTrail(Session, this);
            }
            return auditTrail;
        }
    }


The solution I am promoting allows you to keep the layout less complex and invoke this rarely used or quite advanced feature from a small PopupWindowShowAction showing a ListView:


It will be interesting to hear about your preferences in this regard. Please let me know in comments. Thanks!


Tuesday, June 20, 2017

Performance tuning of the saving/validation process using the PersistenceValidationController events

Regardless of how good and sophisticated your development tools are, real production use often imposes research and solving speed issues. In this tip, I will talk about tuning the Validation Module to do its best when saving a master object exposing  large collections of aggregated data. 

By default, aggregated objects are considered to be an integral part of a master object, and thus, they should be validated together with the master object, which may take significant time if you have hundreds or thousands of complex detail records. The entire detail collection will be loaded and validated in this instance.

The good news is that XAF is very flexible and has a customizable framework that provides many ways to intercept this validation process. 

Tuesday, March 7, 2017

How to change an Application Model option globally or for multiple nodes

I have recently updated one of the articles on the subject in our support knowledge base and wanted to test-drive this content with you: https://www.devexpress.com/kb=T271022


Since the Application Model basically represents a skeleton of the application UI, based on which visual controls for supported platforms are created at runtime, updates to various options in the source UI metadata (both at design time and runtime) can be a good and often platform-agnostic alternative to customizing underlying controls directly in Controllers or other UI entities (examples: one, two, three). The most difficult thing is to perform this update at the right moment or using the right event in the View life cycle!
Even though this may sound like a quite an advanced topic, this is one of the core concepts for our framework, which I recommend you get familiar with.







Your feedback is welcome, as always!

We also hope to use this KB as a base for future updates of the online documentation at  Concepts > Application Model  for easier discoverability, so your early feedback on the main methods I described is welcome. In particular, I would greatly appreciate your comments on whether you experienced the scenarios needed runtime Application Model updates and exactly which techniques you used (e.g., #2.1, 2.2 or all ).


Thursday, February 23, 2017

How to refresh View appearance after making changes to the Application Model in code

With XAF v16.2.4, you can apply Application Model changes to a View without recreating it. To do this, save the Frame's View to a variable and then unlink it from the Frame by passing null to the SetView method. After that, make the required changes to the model, call the LoadModel method with the false parameter and then set the saved View back to the Frame using the SetView method. Here is the generic code illustrating this pattern:

View view = Frame.View;
if(Frame.SetView(null, true, null, false)) {
    // Make required changes with the model here. 
    // ... 
    view.LoadModel(false);
    Frame.SetView(view);
}

You can find a full ViewController code for accomplishing the two most popular WinForms scenarios benefiting from this capability in the https://www.devexpress.com/kb=S173664 article (switching a ListView editor type and MasterDetailMode). 
This video also illustrates how it works in the application UI in action. 


Leave a comment if this is something you are going to try right now!
As always, please report any issues using the https://www.devexpress.com/ask service. Thanks in advance!


Thursday, October 13, 2016

How to map Actions to a certain RibbonPage and RibbonGroup via the Application Model

This is my second post about advanced ribbon menu customizations in XAF WinForms apps. This time I want to repost two possible solutions for the aforementioned task after reviewing and updating the code of one good (and never old - Hi, Noxe!:-)) customer recently. This work was done after an interview about my Simplifying customization of Action controls - YOUR FEEDBACK IS NEEDED! post. Take a look at it if you haven't yet. 


Long story short, refer to the https://www.devexpress.com/kb=S134617 ticket and find two possible Controller implementations. Even though the first one (RibbonFromModelWithEventController.cs) requires more code to implement, I like it more, because it does not require you to create an Action Container node manually in the Model Editor. With the first one, you just specify the TargetRibbonPage and TargetRibbonGroup properties for a required Action under the ActionDesign node and you are done:


In any case, I suggest you play with both implementations and watch the attached video to determine what is more suitable for you. I look forward to hearing from you in the comments section or in the Support Center, as always.


I do not want to focus much on the Controller code itself, just want to note that there we extended the standard IModelAction interface corresponding to the ActionDesign | Action node and then handled these new options in our code. This is one of my favorite Application Model features, which is also truly loved by our customers. In fact, everything you see in our framework is built using the same simple principle: you have certain UI metadata or settings store and have some Controllers in modules that create/customize visual controls accordingly. To learn more about this, refer to the Concepts > Application Model > Extend and Customize the Application Model in Code article in our online documentation. This is a really cool feature and it can help you create a more reusable code.

Wednesday, October 5, 2016

How to place all nested View commands into the main ribbon and activate them based on the selected layout tab

My next two posts will be devoted to advanced ribbon menu customizations in WinForms, which become much easier to implement with the introduction of the new Ribbon and Standard templates (WinApplication.UseOldTemplates = False) back in v14.2 and also API changes in the recent XAF versions.

The current post is about mapping ALL Actions from the nested Frame toolbar into the main ribbon menu by creating a separate page. It is planned that when you activate a certain nested ListView within a layout tab, its related View commands will be activated in a separate ribbon page as well (context-dependent commands). This somewhat exotic approach was requested a few times by different customers and is likely dictated by users who have a habit of using only the main ribbon menu, i.e., without moving the mouse to the bottom context.

The two pictures showing how it was before and after making necessary code changes + a video showing everything in action are worth a thousand words in communicating this effect in the real app.
Context-dependent Actions in ribbon

Thursday, July 14, 2016

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.

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.

Tuesday, March 29, 2016

How to change the default error icons for failed validation rules

I've just updated the corresponding Support Center ticket and want to share one more advanced example on using the built-in ImageLoader API with you. Before reading further, please learn more on this helper class from its docs or from my previous post on the same subject: 




Monday, December 14, 2015

DashboardView - Allowing end-users to delete created dashboards via the application UI

In v15.2.4 we have added the DeleteDashboardsController which provides the DeleteDashboard Action. This Action is located in the Tools category and invokes a popup dialog with a list of all dashboard views defined in the user's model differences.

In this popup you can select one or more dashboards and click Delete to remove them. The DeleteDashboardsController.CanDeleteParentGroup property specifies whether or not the dashboard's parent group is deleted when you remove the last dashboard in this group. 

The DeleteDashboard Action is active when there are dashboards that can be deleted and the EnableCreation property of the Options | Dashboards node is set to true in the Application Model.


Previously, it was only possible to manage these user-defined dashboards via the Model Editor or in code. So, I hope you will now be able to enable this feature for your clients without the fear of being overloaded with support calls about removing unwanted stuff.

You can find more information on this XAF feature in the online docs here:

Tuesday, August 25, 2015

Getting ready the ConditionalAppearance module infrastructure for custom options of the extended AppearanceAttribute (e.g., tooltip)

First of all, this piece of information is quite advanced, so be sure you are well-aware of the module's basic functions and main extensibility and customization points, at least through AppearanceController. If not, check out the related online documentation before reading further. 

Customer scenario

Would it be possible to add in the conditional appearance module the possibility to show a tooltip in the cell in listView when the 
condition is satisfied? (you get different color based on criteria and when you move to the cell a tooltip is shown telling you why the color is different ), example:

[C#]
[Appearance("CategoryColoredInListView", AppearanceItemType = "ViewItem", TargetItems = "Category", Criteria = "Category = 'Seafood'", Context = "ListView",FontColor = "Blue", Priority = 1, ToolTip="the tooltiptext!!!!")]

Monday, August 24, 2015

How to place an Action in a different location programmatically

I think that many people know that they can control this visually by drag&drop under the ActionDesign | ActionToContainerMapping node in the Model Editor, but just a few know of the best code solution. A good scenario when it is necessary to handle this requirement in code is described by our customer in this Support Center ticket (more real user scenarios can be found here).

After receiving enough requests for this, we decided to put a full example solution in our docs. It is based on handling a single CustomizeContainerActions event of the built-in ActionControlsSiteController (or FillActionContainersController class, if your form template does not support the IActionControlsSite  interface).

Do not miss this new online documentation and hopefully, it will help you spend less effort on accomplishing your advanced business requirements in our framework.

Thursday, July 23, 2015

Making the AuditTrail functionality operate correctly with several XPObjectSpaceProviders when storing data in separate databases (15.1.6)

I wanted to inform the community of a solution we have just finished testing for the next XAF version in response to the following customer's business scenario:

"i followed this instruction to work with two databases in one application. so far so good. 
i also managed to include the security module and get it working, but now i don't know how to use the "audit trail" module! it doesn't seem to matter in which project i include it, but it will not save anything to the database."


As you probably know, XAF supports connecting to several databases and even using both Entity Framework (EF) and eXpress Persistent Objects (XPO) at the same time (examples: one, two, three), although it is not the primary scenario, to be honest. 

In short, if you were in need of such a configuration and wanted to have AuditTrail capabilities, it would "just work" starting with v15.1.6. If you feel confident to check technical details on this, see my description in the T263982 - AuditTrail - Ensure support for scenarios with several XPObjectSpaceProviders ticket.
By providing support for this module, we continue working in the direction we took in the past, which I also discussed in the past blog. As always, our team is looking forward to hearing your feedback in this regard.

Tuesday, July 7, 2015

How to load an icon for an XAF UI element from the database instead of using predefined images from assembly resources or file system

Scenario
In my opinion, this is quite an advanced scenario, but I still want to share a simple solution for it using the built-in ImageLoader API provided by our framework. If you are interested in a real life scenario, then it is described in this Support Center ticket by one of our customers:

"I have a SingleChoiceAction which I'd like to use to set the status of the selected objects in a view. The possible status values come from a lookup table, which also contains a SmallIcon property which I'd like to use for the image of the items but the ChoiceActionItem only has an ImageName property to use an Embedded Resource. How do I use the images from the database instead? Putting the images as Embedded Resources defeats the object of storing them in the database - any new values would require the addition of a new Embedded Resource, a programming change."




Friday, June 26, 2015

Creating associations between XPO data models in code using the XafTypesInfo API



Prerequisites:
See my About XAF Types Info Subsystem... blog post before reading.

What's New in this regard?
Just wanted to inform you guys that starting with v15.1.4, you can use the solution described in the eXpressApp Framework > Concepts > Business Model Design > Types Info Subsystem > Customize Business Object's Metadata > Create Associations in Code article for that purpose:

The following snippet illustrates how to declare an association between two class' properties when you have no access to these classes code and cannot apply the AssociationAttribute directly.

C#
ITypeInfo typeInfo1 = typesInfo.FindTypeInfo(typeof(DomainObject1));
ITypeInfo typeInfo2 = typesInfo.FindTypeInfo(typeof(DomainObject2));
IMemberInfo memberInfo1 = typeInfo1.FindMember("Object2");
IMemberInfo memberInfo2 = typeInfo2.FindMember("Object1s");
if(memberInfo1 == null) {
    memberInfo1 = typeInfo1.CreateMember("Object2", 
        typeof(DomainObject2)
    );
    memberInfo1.AddAttribute(
        new DevExpress.Xpo.AssociationAttribute("A", 
        typeof(DomainObject2)), true
    );
}
if(memberInfo2 == null) {
    memberInfo2 = typeInfo2.CreateMember("Object1s", 
        typeof(XPCollection<DomainObject1>)
    );
    memberInfo2.AddAttribute(
        new DevExpress.Xpo.AssociationAttribute("A", 
        typeof(DomainObject1)), true
    );
    memberInfo2.AddAttribute(
        new DevExpress.Xpo.AggregatedAttribute(), true
    );
}
((XafMemberInfo)memberInfo1).Refresh();
((XafMemberInfo)memberInfo2).Refresh();