eXpress App Framework Team

April 2011 - Posts

  • XAF – Core & Performance Improvements (coming in v2011 vol1)


    Do you remember last great performance improvements we introduced in versions 10.1 and 10.2? Now, I’m pleased to report that the upcoming major release is no exception! You might already have heard some details on further improvements we planned for our framework in forums, but I want to fully devote this blog to describing what we achieved in this regard. So, let’s start!

    Caching of metadata, explicit types registration…

    Starting from version 11.1, the information about domain components as well as the application model is generated only once, during the first application run. Then, this information is automatically saved on the disk and loaded during subsequent application runs. So, don’t be surprised if you detect two service assemblies in the application folder after it is run for the first time. These are DcAssembly.dll and ModelAssembly.dll respectively. There will be also one more file without any extension – ModulesVersionInfo. Its purpose is to keep version information for modules used in your application. If you open this file in your favorite text editor, it may look like this:XAF_Rocket

    \XProjectModule 1.0.4134.34463
    \XProjectWindowsFormsModule 1.0.4134.34463

    XAF uses the information from this file to decide whether cache assemblies should be generated or not. So, if the module versions remain unchanged, XAF will load ready information about domain components and application model structure from the DcAssembly.dll and ModelAssembly.dll libraries. Otherwise, it will remove existing cache assemblies (if found) and store the generated information on disk, and then update the information in the ModulesVersionInfo file (if it does not exist, it will be created).

    I can anticipate the next question you want to ask: How much faster is this caching approach? We measured the startup time of several 10.2 applications and compared it with their respective 11.1 versions. The average improvement starts at 20%. It may vary from application to application though. In any case, we think that it is one more significant step forward in making XAF more user friendly, and we hope that end-users will notice this small improvement.

    Some of you will remember our ambitious goal - halve the startup time, which we discussed in our Roadmap 2011. To be honest, we hoped that caching would help us eliminate more startup time, and when it did not, we of course researched other ways of doing this.

    We have also optimized how the information about types (controllers, business objects, modules, etc.) is collected in XAF. As part of this, the ModuleBase class was greatly refactored and simplified. For instance, a bunch of properties like AdditionalBusinessClassAssemblies, AdditionalBusinessClasses, BusinessClassAssemblies, BusinessClasses, DeclaredBusinessClasses, as well as their respective virtual methods, were eliminated and replaced by a small set of *ExportedTypes members. In addition, the ModuleBase class now exposes a set of *ControllerTypes members. Both can be used to explicitly register business objects and controllers respectively, to be used by the module, instead of automatic searching for all the matched types within the module assembly. At once, we refactored all standard XAF modules to take advantages of these improvements. For example, this is what the registration code of the ReportModule looks like in 11.1:

      1: protected override IEnumerable<Type> GetDeclaredExportedTypes() {
      2:     return reportDataType == null ? new Type[0]: new Type[] { reportDataType };
      3: }
      4: protected override IEnumerable<Type> GetDeclaredControllerTypes() {
      5:     return new Type[] {
      6:         typeof(CustomizeNavigationItemsController),
      7:         typeof(InplaceReportCacheController),
      8:         typeof(PrintSelectionBaseController),
      9:         typeof(ReportDataSelectionDialogController),
     10:         typeof(ReportServiceController)
     11:     };
     12: }
    You may ask what will happen to your custom modules? Will your custom controllers and business objects still be automatically collected and registered in 11.1? Yes, they will, but we recommend you perform similar refactorings in your custom modules. All these tricks are intended to achieve some additional improvements to the overall startup performance.

    Future plans

    As always, we do not plan to stop at what we already achieved, and you should expect more good news in future releases. One of our upcoming goals in this direction is to minimize the number of system assemblies used in XAF. Let’s imagine the worst case, and count the number of required assemblies for the needs of a single XAF application. We currently have about 50 system modules and each of them is represented by a separate assembly. Add to this the number of custom modules you might have already developed for your needs or the number of third-party assemblies like eXpand and finally the number of required DXperience assemblies, and it is easy to reach one hundred assemblies overall. This huge number is not only difficult to manage by developers, but it also can be a performance pitfall - the more assemblies, the more time CLR requires to load them. I am not even talking about the compilation time here. Hence, we want to make it possible to have more than one XAF module within a physical assembly. I cannot promise anything or say more at this time, but it is possible that one day we may literally have only a few assemblies, like DevExpress.ExpressApp.dll, DevExpress.ExpressApp.Win.dll, DevExpress.ExpressApp.Web.dll, containing all the necessary system modules. I think that would be paradise to manage and deploy for developersclip_image002.

    Again, this is only current thought and we will have to wait for the final results of our research in this regard. Of course, we will also consider further how to optimize the types info subsystem, because populating it currently takes most of the startup time, and it seems that we have already reached the limits of .NET Reflection speed here. Anyway, we will see how it is progressing, and hopefully, we will be able to keep our Roadmap promise (halve the startup time) by the end of 2011.

    Please give us your feedback!

  • XAF - EasyTest Improvements (coming in v2011 vol 1)

    As you know, XAF is shipped with EasyTest functional test framework. In the upcoming release, we made a number of changes in the EasyTest script commands. Several new commands were introduced, and the existing commands functionality was extended. The main aim of the improvements we made is to simplify testing of XAF applications that have both Windows Forms and ASP.NET versions.

    Although XAF can produce Windows Form and ASP.NET applications with the same functionality, there are differences in their behavior. Previously, you had to use the IfDef EasyTest command to control test flow, depending on which application is testing. Commonly encountered issues are:

    - To modify the current object in ASP.NET applications, you should switch the Detail View to edit mode via the Edit Action. There is no Edit Action in Windows Forms applications, as the Detail View is initially editable.

    - The broken validation rules are displayed in a different manner. In Windows Forms applications, the ValidationWindowsFormsModule module handles broken rules and displays validation results in a separate View. In ASP.NET applications, the validation error messages are displayed as any other error messages in the current page via the ErrorInfoControl control (see Error Handling in ASP.NET Applications).

    There are other differences in behavior, but the two above are most significant. The following improvements were introduced to a number of IfDef/EndIf commands in tests.

    OptionalAction command introduced

    The new OptionalAction command acts like the old Action command. The difference is that this command does not require the target control to be visible and active. If the Action is unavailable, this command simply does nothing. Let us consider the following script snippet:

        1 *ProcessRecord

        2  Last Name = Tellitson

        3 #IfDef MainDemoWin

        4 Action Edit

        5 #EndIf

        6 *FillForm

        7  Birthday = 11/28/1980

    With the new OptionalAction command, it can be rewritten in the following manner:

        1 *ProcessRecord

        2  Last Name = Tellitson

        3 *OptionalAction Edit

        4 *FillForm

        5  Birthday = 11/28/1980

    CheckValidationResult command introduced

    The new CheckValidationResult command tests the validation results that are currently displayed. It supports both Windows Forms and ASP.NET representation of validation results (pop-up window and ErrorInfo control, respectively). The following secondary parameters can be specified:

    · Message - optional. Checks the primary validation error message.

    · Columns - optional. Considered for Windows Forms applications. It specifies captions of the DisplayableValidationResultItem List View columns to be tested. You can specify two Target and Description column captions, or a single 'Description' column. If the Columns parameter is omitted and the Info property specifies a target name and a description text, then columns with the "Target" and "Description" captions are tested. If the Columns parameter is omitted and the Info property specifies a description text only, then a column with the "Description" caption is tested.

    · Info - optional. Checks validation results (rule target and description) of each broken rule. You can specify target name and description text separated by comma, or description text only.

    · SkipUnexpectedErrors - optional. When set to True, disables checking the validation errors that are not specified by Info parameters. The default value is False, so the CheckValidationResult command execution fails when there are unexpected validation errors.

    Let us consider the following script snippet that can be used to test validation results in previous version of XAF:

        1 #IfDef MainDemoWin

        2 *CheckFieldValues

        3  ValidationResultsText = Problems were detected during data validation. Please read the information below to understand what the issues are and how you can correct them.

        4 *CheckTable

        5  Columns = Description

        6  Row = "Title" must not be empty.

        7 *Action Close

        8 #EndIf

        9 #IfDef MainDemoWeb

       10 *FieldVisible ErrorInfo

       11 *CheckFieldValues

       12  ErrorInfo[0] = Problems were detected during data validation. Please read the information below to understand what the issues are and how you can correct them.

       13  ErrorInfo[1] = - "Title" must not be empty.

       14 #EndIf

    With the new CheckValidationResult command, it can be rewritten in the following manner:

        1 *CheckValidationResult

        2  Message = Problems were detected during data validation. Please read the information below to understand what the issues are and how you can correct them.

        3  Info = "Title" must not be empty.

        4 *OptionalAction Close

    Note a use of the OptionalAction command in this scenario. It closes the validation pop-up window in the Windows Forms application.

    New capabilities of the HandleDialog command

    Now, this command supports messages displayed via the ErrorInfoControl in ASP.NET applications. So, this script snippet:

        1 *Action Log On

        2 #IfDef MySolutionWeb

        3 *CheckFieldValues

        4  ErrorInfo = Login failed for 'UnExistingUser'. Make sure your user name is correct and retype the password in the correct case.

        5 #EndIf

        6 #IfDef MySolutionWin

        7 *HandleDialog

        8  Message = Login failed for 'UnExistingUser'. Make sure your user name is correct and retype the password in the correct case.

        9  Respond = OK

       10 #EndIf

    …can be rewritten as:

        1 *Action Log On

        2 *HandleDialog

        3  Message = Login failed for 'UnExistingUser'. Make sure your user name is correct and retype the password in the correct case.

        4 *OptionalAction OK

    Additionally, the HandleDialog command takes the optional Caption parameter now. You can check the active window caption in a Windows Forms application and the document title in an ASP.NET application with this parameter:

        1 *HandleDialog

        2  Caption = MainForm

    Another significant improvement is that the HandleDialog command supports browser’s confirmation messages now (for instance, displayed when executing an Action that has the ActionBase.ConfirmationMessage property specified). To test confirmations in an XAF application that was updated from the previous XAF version, remove the following line from the Application_Start method in the Global.asax.cs file:

    ConfirmationsHelper.IsConfirmationsEnabled = false;

    The FillForm command improvements

    Previously, to select a value in a lookup field, you had to write the following code:

        1 #IfDef MySolutionWin

        2 *FillForm

        3  Department = Sales Department

        4 #EndIf

        5 #IfDef MySolutionWeb

        6 *ExecuteEditorAction LookupField(Find)

        7 *Action Filter by Text(Sales Department)

        8 *SelectRecords

        9  Columns = Name

       10  Row = Sales Department

       11 *Action OK

       12 #EndIf

    The FillForm command supports Lookup Property Editors in ASP.NET applications now, and this test can be much simplified:

        1 *FillForm

        2  Department = Sales Department

    The ExecuteEditorAction command improvements

    Previously, to execute an action displayed within a lookup, you had to write the following code:

        1 #IfDef MyAppWin

        2 *ExecuteEditorAction Status

        3 *Action New

        4 #EndIf

        5 #IfDef MyAppWeb

        6 *ExecuteEditorAction Status(New)

        7 #EndIf

    Now you can pass an argument to the ExecuteEditorAction command when testing Windows Forms applications. So, the IfDef commands are not required:

        1 *ExecuteEditorAction Status(New)

    Wildcard support

    You can use the question mark (?) and asterisk character (*) as wildcards in parameter values EasyTest commands. The ? wildcard substitutes for any one character, and * - for any zero or more characters.

        1 *CheckValidationResult

        2  Message = Problems were detected during data validation.*

    Preceded ? and * with a backslash (\), if you test a text that actually contains these characters.

        1 *HandleDialog

        2  Message = Do you want to cancel your changes\?

    To test that an error message was not displayed, use the following code:

        1 !HandleDialog

        2  Message = ?*

    What do you Xafers think of EasyTest? Do you see anything missing?

    Happy EasyTesting!

  • Thinking of Testing… Enter EasyTest

    Testing is a new buzzword in a modern software development world. And we all recognize the importance of it (I hope). However for some of us testing hasn’t found its way into our development process.

    But why is that ? The usual answer is this: I do not have time to spend on that.

    I believe that in most cases this answer comes from small companies or even one man shops. Do they even have alternatives?

    1. Write bug free code. That can work when the project is small. Of course as the time passes any changes you make to the code may interfere with other parts of the project and produce unexpected bugs
    2. Target projects that you are able to test manually. Those projects have to be relatively small and the developer on every release have to go through all the functionality and test it manually

    A real use case of EasyTesting
    I think most of you remember the changes that DX introduced in v10.1 regarding core functionality and application model. To refresh your memory I will point you to this Application Model Migration Guidelines article. When DX started to build core parts of XAF many years ago they chose the technology that had limitations (don’t we always do that?). Luckily for us DX is always prepared for such scenarios. From the very beginning the team, using the EasyTest framework, described all core functionality in a platform agnostic way. That move was a life saver! Developers could rewrite the core and be comfortable about the results, as long as they satisfy the existing EasyTests.

    Easier said than done, some of you may say. Not quite true! Let me compare it with traditional testing.

    Unit Testing: Mostly used for low level testing and does not ensure bug elimination. One reason is that when units collaborate in a higher level the behavior there is unpredictable. And unit tests do not operate at that level.
    Functional Testing: In many cases it eliminates the need for unit testing. The reason is that you are testing how the system operates in a higher level and that of course includes the collaboration of your units. So when you do functional or behavior testing you describe your requirements in a very readable way to target the appropriate level. Using this kind of testing assures that your tests will be less fragile than unit tests. The problem here is that tests may require a very good knowledge of every part of potentially large system (XAF). Which means that it may take a considerable effort to set up full set of tests.

    I believe EasyTest comes to the rescue here. XAF architecture defines the boundaries with the environment. The interaction with the user comes from the Actions. We mostly have to deal with business objects which that are bound to a UI in a transparent way. Using all that together we can build a domain specific language which is exactly what EasyTest is.

    So If we try to write a test in pseudo code will look like this:


    Which gives us the following:

    1) It is non chatty
    2) It is very readable
    3) It tests our application data. Remember that XAF applications are data driven? Testing the database data makes our tests platform agnostic as well!
    4) It did not take long time to write it. Just try to remember how many times you went to a view and hit an action to check a for a behavior.
    5) It is already very close to EasyTest’s original language.

    To learn the basics I highly recommend to start from here. To learn more than the basics, you can watch this great webinar from Gary Short Functional testing deep dive. And, of course, follow my next posts as I am going for a deep dive as well.

    1. EasyTest and test data

    Is there anything else that can raise the quality (and, perhaps, the price) of your products apart from an excellent testing framework? If yes, I’d like to hear about it and we can blog about it too Smile

    Happy EasyTesting!

  • XAF - Eliminating the number of Conditional “Something” (coming in v2011 vol1)


    I believe that every XAFer has used or at least heard about a set of extra modules XAF currently provides for customizing the appearance of editors used in List and Detail screens, most often against certain business conditions. As you guessed, I am talking about the Conditional Formatting and Conditional Editor State modules here. These modules are already quite old (the first was introduced in 8.1 and the latter in 9.2) and plus they provide different approaches for achieving similar goals. For example, in Model Editor, you are limited to creating Conditional Formatting rules, when with the Conditional Editor State module you can either define customization rules in code, via attributes or in the application model, via the Model Editor. Another example, the Conditional Formatting module works in List View only, when the Conditional Editor State supports both View types. At the same time, the latter module works for the Grid List Editors only, when the first module supports other List Editors, like Tree List. There are of course lots of other differences in behavior and also business reasons, like maintaining two different code bases – that forced us to think about providing a unified solution for solving the original task of customizing the appearance of editors.

    When one is better than two…

    As a result, and based on the great customer feedback we received in version 10.1 we provided a new Conditional Appearance module that was designed to supersede the two old Conditional XXX modules. This module not only takes advantage of both modules, but also provides some unique features that did not exist in its prototypes, like the capability to conditionally customize the appearance of Actions.

    It is now 2011 and almost one year has passed since then, and of course XAF did not stand still for all this time, and so it is understandable that we want to optimize the team’s resources on supporting the old modules to better evolve our framework. So, in the upcoming v2011 vol1 release, we marked the Conditional Formatting and Conditional Editor State modules as obsolete (soft). If you are still using these modules in your solution, you will receive a warning during the compilation of your project. Although this is just a warning, not an error, and the modules will continue to work as they worked before, it is strongly recommended to remove your old rules (either declared in code or in the application model) and migrate them to the new Appearance rules, provided by the Conditional Appearance module. This is because in version 11.2, we are planning to completely mark these modules and all the stuff from them as obsolete, resulting in a compilation error and leaving you no choice, but removing the old modules from your solution. The experience of other customers, who have already migrated their rules in the past shows, that the migration will be smooth, because these Appearance rules are very similar to the old ones. In addition, there are plenty of examples in the docs and our demos, demonstrating how to implement all the possible scenarios using the Conditional Appearance module.

    Let us know your thoughts!

    I hope that you support and understand our decision, and will have no problems migrating the old rules. Should you have any difficulties, our Support Team will be glad to help resolve them, as always. Also, we are open to your feedback about further improvements of the Conditional Appearance module. So, if it is missing some important functionality, feel free to drop us a line in the comments to this blogs, or better yet, log your suggestions via the Support Center. We will be glad to review them.

  • XAF - Merge User Differences from a Custom Model Storage

    Recently, we announced a new Model Merge feature that will be available with the v2011 vol 1 release.  There was a lot of positive feedback in comments, thanks for that. But the question was - if it is possible to merge a user model stored in a database (this approach is described in the K18137 knowledge base article). The answer is YES, it is possible. All you need is to add a simple Controller that contains Export User Differences and Import User Differences actions.


    The Export User Differences action exports user model differences from a database (or another custom storage) to a regular XAFML file that can be opened in the Model Merge Tool at design time. The capability to import XAFML files is provided by the Import User Differences action. We will have updated the K18137 article by the upcoming release to illustrate this Controller implementation.

    Application administrators can use the Model Merge feature too.  Of course they have no access to the application source. But they can merge differences into a common model layer that is typically stored in the Model.xafml file in the application folder. This can be done via the Merge Differences command available in Model Editor at runtime.


    So, an administrator can customize a View, and then provide it to all users without disturbing the application developer. In this instance, the Model.xafml file must be shared among all end-users. If terminal server deployment is used, this file is shared initially. Otherwise, an administrator needs to re-deploy the Model.xafml file for all users.  However, database storage can be also implemented for the shared model layer, by handling the XafApplication.CreateCustomModelDifferenceStore event. We will have updated the K18137 article by the upcoming release to show how to handle this event.

  • XAF – Improved ASP.NET UI Performance (coming in v2011 vol 1)

    While working on the XAF v2011 vol 1 release, we have introduced several performance improvements which we think are worthy of being blogged about. Check them out.

    First of all, we have substantially reduced the size of generated pages. Second, the lightweight rendering mode is now enabled by default. Although this mode could be enabled manually in XAF applications since v2010 vol 2.4, quite a number of issues has been discovered since then, which practically prevented this mode from being used in production. I am happy to say that we have fixed these issues in XAF v2011 vol 1. We have also reworked XAF internals to speed up page generation on the web server.

    So, how much faster your ASP.NET XAF application is going to be? Take a look at the following tables.


    These are the results of comparing the performance of MainDemo v2010 vol 2 against MainDemo v2011 vol 1. The applications were deployed onto the web server on a remote machine with a local SQL server instance. To make the testing a bit more realistic, we have populated the database with several million rows of sample data. No additional set up has been performed, so MainDemo v2010 vol 2 used classic rendering mode and the v2011 vol 1 version of MainDemo used lightweight rendering.

    As you can see with XAF v2011 vol 1, network traffic has decreased roughly two times. Moreover, pages were served by the web server 21% faster in client mode and about 36% faster when server mode was enabled.

    We think these are pretty notable results.  We also hope your users will enjoy your application much more after these improvements. What do you think? Please let us know!

  • XAF – Model Merge Tool (coming in v2011 vol1)

    End-users can customize an XAF application user interface at runtime with ease. The Layout Manager, Column Chooser and other capabilities allow end-users to configure a UI in a "What You See Is What You Get" way. But when you, as a developer, customize a UI in the Model Editor, you have to deal with indexes, widths, heights, groups, etc. So, you may want to customize a UI as an end-user, and then merge changes to one of the Application Model layers in your XAF solution.

    With the v2011 vol 1 release, we have introduced a new XAF design time functionality - Model Merge Tool.


    This instrument is intended to merge Application Model customizations into an underlying model layer. It means that now you can customize a View items layout at run time, and then move down these changes into the module project layer. Of course, the layout is not the only customization that can be merged - you can merge any differences that can be applied to a target model layer. The most evident use cases are merging Detail View and Dashboard layouts, grid customizations (columns order, visibility, grouping, etc), chart and pivot grid settings.

    Let us take a closer look on how to use the Model Merge feature with the MainDemo application. Assume that we have customized the Resume List View at run time (for instance, changed columns order):


    The customizations we have made are automatically saved to the Model.User.xafml file located in the project output folder:

    <ListView Id="Resume_ListView">
        <ColumnInfo Id="Contact" Index="0" />
        <ColumnInfo Id="File" Index="1" />

    Now let us merge the end-user customizations into the Application Model of the module project. In the Solution Explorer, right click the MainDemo.Win application project and click Merge User Model. In the invoked Open dialog, choose the Model.User.xafml file. As a result, the Model Merge Tool dialog is invoked. Navigate to the Resume_ListView node in the tree list. This node caption is displayed in bold, as the node contains customizations. Use the checkbox to the left to select this node. In the dropdown below, select MainDemo.Module and click Merge. The Resume_ListView node's differences will be merged into the MainDemo.Module project.


    Finally, click Save to persist changes and close the Model Merge Tool dialog. After that, you can see the Resume_ListView node customizations in the Model Editor invoked for the MainDemo.Module project.



    As the differences were moved into a platform-agnostic module, they affect the ASP.NET application as well:




    In the Model Merge Tool, you can select several nodes at once, and repeat the merging operation as many times as required, before clicking Save. If a part of the selected differences cannot be applied to the selected target, a warning message will be displayed. In this instance, you can try another target (e.g. MainDemo.Module.Win).

    If your application is already deployed, and one of end-users has a carefully crafted layout, you may want to use this layout in a new version of the application. In this instance, just copy the Model.User.xafml file from the end-user workstation, and select this file in the Open dialog when running the Model Merge Tool.

    If you want to merge differences from an application or module project into an underlying module, select the Merge Model item instead of Merge User Model in a project’s context menu. The Model Merge Tool will be invoked for the current project in this instance.

    The following video illustrates the Model Merge Tool in use:

    What do you think about this addition to the framework? Please let us know!

    UPDATE: We have posted a new Merge User Differences from a Custom Model Storage blog that describes how to merge a user model stored in a database.

  • XAF - Model Editor Usability Improvements (coming in v2011 vol1)

    When you develop XAF applications, you work not only within the Visual Studio code editor, but use XAF design-time features intensively. Model Editor is the designer that you use most often, so its usability is critical. Let us consider the improvements we made in the upcoming release.

    Image, Criteria and Edit Mask editors

    There are string properties that specify image names, e.g. IModelClass.ImageName, IModelAction.ImageName, etc. Previously, you had to type an image name manually. Now you can browse the available images within the Image gallery dialog.


    To specify criteria expressions in the Model Editor, you should be familiar with the Criteria Language Syntax. Certainly, every experienced XAF developer knows it well, but what about application administrators who also may have to deal with the Model Editor? Now, the Criteria Editor dialog is available for properties that represent criteria expressions.


    Now, you can specify an appropriate Edit Mask with ease, as the Mask Editor dialog is available.


    Nodes grouping

    In a node’s context menu, you can see the Group/Ungroup command. Currently, you can group child nodes by the namespaces of their associated objects. The screenshot below illustrates the grouped Views node. With this feature, you can easily separate Views of your custom business objects from Views of objects declared in other XAF modules.


    You can also group Action, Class and Controller nodes.

    Linked nodes

    Now you can find that many nodes have a “virtual” child node named Links. Under this node, you can see nodes that contain references to the current node. The screenshot below illustrates the Department node of the IModelClass type. Within the Links node, you can see the Creatable Item for the Department object, Members of the Department type and Views designed for the Department type.


    You can edit properties of linked nodes in place, or navigate to an actual node location via the Go to Source Node command.

    Standalone Model Editor Improvements

    The standalone Model Editor can be used by application administrators to edit a model of the deployed ASP.NET application or Windows Forms application with the Edit Model action disabled. Previously, to start the standalone Model Editor, you had to pass the configuration filename or a module assembly filename as a command-line parameter. Now you can run it without parameters, and select the required file in the Open Model dialog.


    To edit the Application Model of the deployed XAF application, you should specify the configuration file name only. An option to choose an assembly file and model differences path provides the ability to edit the model of a specific module outside of Visual Studio.



Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at or call us at +1 (818) 844-3383


DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2017 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners