Blogs

Gary's Blog

November 2010 - Posts

  • Webinar – Technical Debt

         

    For those of you who missed it, or for those of you who tuned in but who struggled to follow what was going on because of the sound issues. I have re-recorded my Technical Debt talk and it is now available on our video site. I’d be interested to hear what you guys have to say on this topic, I have a real interest in this and, of course, it’s a subject that touches every developer, architect and ITPro, so feel free to make your thoughts known in the comments.

  • XAF - Dog-Fooding with Conditional Appearance

         

    As many of you might already know, we are successfully using XAF for many our internal applications. For example, our bug and support issues tracking applications (DXSupport, having both Win and Web parts) and applications for maintaining sales (MyDX). In this blog post I would like to show you how we utilize the Conditional Appearance module in the DXSupport application.

    Imagine an Issue business object, representing a base object for various kinds of support issues (e.g. bug reports, questions, suggestions, etc.). It has a HoursActive property, which of course, indicates how many hours an issue has been active. Now this is a very important property when it comes to the internal workflow of the application. We will have several Appearance rules based on this property, which are intended to attract the attention of the DXSupport user to the issue, according to the predefined internal workflow rules. Since DXSupport users cannot recompile the application, the Appearance rules will be defined in the Application Model through the Model Editor:

    Appearance Rules

    And here is the corresponding XAFML code:

    <BOModel>
      <Class Name="DevExpress.MyDX.Issue">
        <AppearanceRules>
          <AppearanceRule Id="IssueListViewActive_0-4" IsNewNode="True" FontColor="0, 192, 0" 
    Criteria="Status.Name == 'Active' AND HoursActive" < #4:00#" TargetItems="*" Context="ListView" AppearanceItemType="ViewItem" Index="0" /> <AppearanceRule Id="IssueListViewActive_4-18" IsNewNode="True" FontColor="MediumTurquoise"
    Criteria="Status.Name == 'Active' AND (HoursActive > #4:00# AND HoursActive" < #18:00# )" TargetItems="*" Context="ListView" AppearanceItemType="ViewItem" Index="1" /> <AppearanceRule Id="IssueListViewActive_18-24" IsNewNode="True" FontColor="MediumBlue"
    Criteria="Status.Name == 'Active' AND (HoursActive > #18:00# AND HoursActive" < #23:59#)" TargetItems="*" Context="ListView" AppearanceItemType="ViewItem" Index="2" /> <AppearanceRule Id="IssueListViewActive_24+" IsNewNode="True" FontColor="192, 0, 0"
    Criteria="Status.Name == 'Active' AND HoursActive > #23:59#"
    TargetItems="ArticleId;HoursActive;Status;AssignTo" Context="ListView" AppearanceItemType="ViewItem"
    FontStyle="Bold" Index="3" /> <AppearanceRule Id="IssueListViewActive_NotAccepted" IsNewNode="True" Index="4" Criteria="!Accepted"
    TargetItems="*" Context="ListView" AppearanceItemType="ViewItem" FontStyle="Bold" /> </AppearanceRules> </Class> </BOModel>

    The settings will be saved in the Model.User.XAFML file in the application folder. Then we can easily redistribute these changes amongst DXSupport users. In turn, other users can modify these rules as required, for instance, change the colours to ones that better suite their purposes.

    Here is one of the screens from the application:

    DXSupport screen

    We would love to hear how you incorporated Conditional Appearance into your projects, so if you want to share with us, please tell us about it in the comments.

    That’s all for this post, so ‘til next time, happy XAF’ing.

  • XAF – Improvements to the Conditional Appearance Module (Coming in V2010 Vol 2)

         

    As you’ll remember, starting from v2010 vol 1.5, XAF shipped with a preview of the Conditional Appearance module. This module allows you to dynamically configure the UI, and is designed to supersede the Conditional Formatting and Conditional Editor State modules. If you are not familiar with this module, you can get started by either watching this video or checking the demos in the XAF’s FeatureCenter. Conditional appearance customizations are very popular in business applications, one of our customers said that he has about 120+ appearance rules in his XAF application.

    Anyway, the good news is that the ConditionalAppearance module will be released in v2010 vol 2 and in this post I want to walk you through some of the improvements we’ve made for this release.

    Tree List Editors Support

    Now appearance customizations are also supported for the Tree List Editors instead of just the Grid List Editors, as it was before. The screenshot below demonstrates a customized Tree List Editor look in both ASP.NET and Windows Forms applications:

    Tree List Editors Support for Customizations

    Support for Custom Appearance Customizations at Runtime

    We have also provided the capability to perform custom appearance customizations in code. In order to do this, we have introduced the CustomApplyAppearance and AppearanceApplied events into the DevExpress.ExpressApp.ConditionalAppearance.AppearanceController class. Both use the event arguments of the DevExpress.ExpressApp.ConditionalAppearance.ApplyAppearanceEventArgs type, providing all the necessary information about the current appearance customization. These events are very similar to the EditorStateCustomizing/CustomEditorStateCustomization and EditorStateCustomized events exposed in the ConditionalEditorState module, and so they can be used for the same tasks, i.e. providing appearance customizations at runtime. These events can be used to provide a different look and feel for selected and unselected cells in the grid (you can find some example code for this in this suggestion). Another example is suppressing the tab stops on disabled Property Editors. For this scenario, we even have a Code Central example, illustrating its implementation using the Conditional Editor State module. There, aren’t we good to you? Smile

    Support for Appearance Customizations for Specific Views Only

    We have also provided the capability to apply appearance customizations for specific Views only. Initially, the Context parameter of an appearance rule could only have one of the three predefined values - DetailView, ListView or Any.

    [Appearance(
        AppearanceItemType = AppearanceItemType.Action,
        TargetItems = "Save; SaveAndClose",
        Enabled = false,
        Criteria = "RuleProperty = 'True'",
        Context = "Any"
    )]
    public class MyClass : BaseObject
    {
        public MyClass(Session session) : base(session) { }
    
        public bool RuleProperty
        {
            //...
        }
    }

    This means that a rule can be active either in Detail Views, List Views or all Views. So, previously, we did not allow you to declare appearance rules targeted at specific Views, but now the Conditional Appearance module supports such functionality. And, based on the feedback we received, we have fixed the oversight so that you can now create View-specific rules. The Context parameter can be specified in the following ways:

    Context

    Appearance Rule's Activity Scope

    Example

    A predefined context - "DetailView", "ListView" or "Any".

    Detail Views, List Views or all Views, respectively.

    Any

    A comma-separated list of View identifiers.

    Specified Views only.

    MyClass_ListView, MyClass_DetailView

    The "Any" predefined context, followed by a comma-separated list of View identifiers.

    All Views except the Views specified via View identifiers.

    Any, MyClass_ListView, MyClass_LookupListView

    The "DetailView" or "ListView" predefined context, followed by a comma-separated list of View identifiers.

    All Detail Views or List Views, respectively, in addition to Views specified via View identifiers.

    DetailView, MyClass_ListView

    As you see, not only can you specify Views where a rule should be activated, but you also have the option to exclude a particular View from an appearance rule’s scope.

    As part of this improvement, the Model Editor now allows you to type-in View identifiers when editing the Context property. The good news is you can still choose a predefined context via the drop-down in a couple of clicks:

    Mode Editor Customization Support

    Support for Custom Layout Items and Customizations

    We have also provided the capability to conditionally hide custom layout items. Before this feature existed in the ConditionalEditorState module, but not in the ConditionalAppearance module, which allowed you to hide only layout items corresponding to the Property Editors of a business object. As part of this work we have also introduced the capability to change the font style and colour of layout items and group captions. For this purpose, the AppearanceItemType enumeration now exposes an additional 'LayoutItem' value. This is how an appearance rule will look in code:

     

    [Appearance(
        "TargetFormattingProperty.Caption.Blue",
        AppearanceItemType = "LayoutItem",
        FontColor = "Blue",
        Criteria = "Priority = 'Low'"
    )]
    public string TargetFormattingProperty {
        get { return targetProperty; }
        set { SetPropertyValue("TargetProperty", ref targetProperty, value); }
    }

    and this is what it will look like in your application:

    Layout Item Customizations Support

    We have also introduced some minor refactorings to improve your experience when configuring appearance rules.

    You can play with most of these improvements in XAF’s FeatureCenter demo. As always, we look forward to your feedback.

    Well that is all for this post, ‘til next time, happy XAFing! Smile

  • Technical Debt Webinar 10:00 AM PST Today!

         

    I’ve written about Technical Debt before but today I’m doing a webinar on the subject. Basically, I’ll be covering the following:

    “Technical debt is the cost of putting off good development practices. This debt, must be paid back to avoid the “interest payments” becoming crippling. This presentation will focus on a number of common developer (and project) anti-patterns that can lead to the build up of technical debt in a project and, having identified these behaviours, we’ll look at techniques to firstly quantify and then to mitigate against them. “

    so If you’ve read my previous blog post, and it sounds like something you feel you need to know more about, then sign up now at: https://www3.gotomeeting.com/register/933159686 and I’ll see you 10:00 AM PST Smile

  • XAF – How to Create a Custom Translation Provider for the XAF Localization Tool (Coming in V2010 Vol 2)

         

    You’ll recall that I already blogged about the new Localization tool coming in 10.2? By default, this tool utilizes the Microsoft Translator ™ service (originally we used the Google Translate ™ service, but we had to switch for licensing reasons). However, one of the notable features of our localization tool is it’s capability to use a custom translation services. That means that you can use alternative translators, such as Google Translate, etc., should you so desire.

    In order to create a custom translator, simply create a custom translation provider class, implementing the ITranslatorProvider interface, or descend your class from the default TranslatorProviderBase class, which already implements the required interface. Both entities are available in the DevExpress.ExpressApp.Utils namespace.

    The ITranslatorProvider interface is quite simple:

    public interface ITranslatorProvider
    {
        string Caption { get; }
        string Description { get; }
        string[] GetLanguages();
        string[] Translate(string[] text, string sourceLanguageCode, string desinationLanguageCode);
        event EventHandler<TranslationProgressEventArgs> TranslationProgressChanged;
    }

    Where Caption specifies the name of a custom translation provider; Description specifies a short description of the provider, for displaying in the translation window; GetLanguages is a method that returns a list of cultures, for which translations are possible; Translate is a method that performs the actual translation, and accepts and returns an array of localized values. Finally, TranslationProgressChanged is an event that is required to inform and update the UI during the translation process. The Progress parameter of the event arguments may be within the 0…1 range. You can also cancel the translation by setting the Cancel parameter to True.


    As an alternative to implementing the ITranslatorProvider interface from scratch, you can create a descendant of the TranslatorProviderBase class, which already encapsulates a good deal of functionality. This class also collects localized values in blocks to shorten the translation based on the online translation services. You should specify the size of the block as well as the separator symbol in the constructor of the TranslatorProviderBase class:

    TranslatorProviderBase(string separator, int textBlockSize)

    For example, the maximum block length for the Google Translate service is 5000, the separator is "<br />" (an html tag representing a new line)

    The TranslatorProviderBase class descendant should also implement methods and properties of the ITranslatorProvider interface, which are not implemented by the base class:

    string Caption { get; }
    string Description { get; }
    string[] GetLanguages();

    Of course, you’ll have to override the Translate method as required:

    public virtual string Translate(string text, string sourceLanguageCode, string desinationLanguageCode);

    because this method should query the required service for the translation.

    You can also override the auxiliary CalculateSentences method if you need to split the localized value into several parts to be localized separately:

    public virtual IEnumerable<string> CalculateSentences(string text);

    The TranslatorProviderBase collects localized values, then splits them into small parts based on the CalculateSentences method and then composes blocks from these smaller parts and processes them via the Translate method.


    To register our custom translation provider class, we can add the following line into the constructor of the platform-agnostic module of our XAF solution:

    using System;
    using DevExpress.ExpressApp;
    using DevExpress.ExpressApp.Utils;
    namespace GoogleTranslatorProvider
    {
        public sealed partial class GoogleTranslatorProviderModule : ModuleBase
        {
            public GoogleTranslatorProviderModule()
            {
                InitializeComponent();
                TranslatorProvider.RegisterProvider(new GoogleTranslatorProvider());
            }
        }
    }

    After registration, the custom translation provider will be available from both Visual Studio and the runtime Model Editor.

    There are other reasons for creating a custom provider, not just preferring one service over another. For example, those who are doing the actual translations in your applications may not have an internet connection and so you may want to create a custom translator provider, utilizing a local dictionary.

    You can download a sample, demonstrating how to create a custom translation provider, utilizing the Google Translate Service, from Code Central (once 10.2 ships Smile).

    Note, of course, that by using the provider from this example you automatically agree to the terms of use of the Google Translate Service, you can find a copy of these terms of use at http://code.google.com/intl/sv/terms.html

    Just before I close, I want to thank Vladimir Boborykin, a software engineer from Russia, who first explored the idea of localising XAF applications using online translation services, and then created the free XAF Model Translator (XafMT) tool for the XAF community. This tool is publicly available at http://xafmt.narod.ru . He has been maintaining this tool since 9.3, and his work has been greatly appreciated by the XAF community.

    Well that’s it for this post, so until next time, happy XAF’ing. Smile

  • TechEd Europe Day 2 – Is Lightswitch in the Wrong Product Group?

         

    I spoke to a number of attendees who had been to the Lightswitch session today. They told me that the presenter walked the audience through Lightswitch and it’s place in the Visual Studio family of products. It quickly became clear to the attendees that there was a certain amount of push back from developers in the audience, the general feeling was that Lightswitch is not a developer tool. The feeling is most certainly that Lightswitch is a power user tool and does not belong in the Visual Studio stable. I mean, what does Lightswtich do? It helps you create Silverlight applications, right? Well I’m a developer, if I want to create Silverlight apps I have ways of doing that already.

    So, if Lightswitch shouldn’t be in the Visual Studio stable, where should it be? Personally, I’d like to see it in the Office stable, as that’s where the power users on the Microsoft platform hang out. People who are already creating “applications” using Excel and Access should now have the ability to create Silverlight applications using Lightswitch for Office. If it were in the Office stable, Microsoft would get a double win. Firstly, devs would get off their backs about there being a “toy” in the Visual Studio line up, and secondly, power users would win because they could stop writing mission critical software in Excel and Access and get their applications on a more “professional” footing.

    So why do so many power users write so many apps in Office tools? Simple. A great many enterprises have outsourced their IT capacity. So now to get even the most simple application written someone has to fill out a form in triplicate, submit it to four different people and pay through the nose for it. Not to mention that when the application finally gets delivered, it’s “a day late and a dollar short”. And why do they go through this pain? Well they have no choice normally as the terms of the outsourcing agreement means that all development and support work on applications must be done by the outsourcing company.

    However, under many such agreements, Office is deemed to be “software of personal productivity” and so falls outside of the agreement, mainly because Office is on every desktop in the enterprise and if the outsourcing company had to support it, they’d never been done fielding calls of the “how to I make titles bold?” variety. However, this loophole means that if someone want a new application, this side of Armageddon, then they can write it immediately using Excel or Access.

    So what do you think, am I right, should Lightswitch be in the Office stable? Leave you comments in the… well, comments. Smile

  • TechEd Europe 2010–Silverlight Drives UX Enhancements

         

    “You ain’t gonna need it!” is a common refrain heard amongst developers and is a good design principle. It speaks to the fact that it is best practice not to over engineer a solution, if “you ain’t gonna need it” then don’t build it into your project in the first place. The more code you write the more bugs you will write, it’s as simple as that. If you think you *might* need it in the future then wait until you *do* need it before coding it up.

    The same, however, cannot be said of product development. I spoke with a Norwegian customer today, who worked on an ASP.Net application for an organisation dealing with nature reserves in Norway. Recently they have ported there application to Silverlight for, he admitted with a smile, “no good reason at all”. However, having made the move, it opened up all sorts of UX and functional improvements that he as introduced to the project.

    The application now sports maps of areas with interactive, drill down features, to expose the underlying wildlife data in the chosen location. He has also introduced in line video information and commentary. He noted that some of the early changes had been driven my him – possibly to justify the move to Silverlight in the first place – but thereafter, once the business had a taste of what was possible, they started coming up with some of their own innovative ideas, and now it is the case that the majority of the enhancements to the project have been driven by them.

    Now, whilst I am not suggesting that you all go out and upgrade your products to the latest and greatest “shiny” thing for “no good reason”, this customer story does illustrate that if you move from a less rich environment to a more rich environment, it can spark off innovative ideas that will, ultimately, lead to improvements in your products.

  • XAF – List Editors, KPI And Dashboard Improvements (Coming in V2010 Vol 2)

         

    In this blog post we’ll take a look at some of the improvements to the Pivot and Chart List Editors, KPI and Dashboard features that I introduced in previous blogs.

    Runtime Dashboard Creation

    The first thing we’ve done is to implement the ability to create dashboards at runtime using the CreateDashboard action. A navigation item for the newly created dashboard view can be created automatically as well. All the runtime changes are persisted in the user model differences file:

    Create Dashboard

    Dashboard Organizer

    Also, dashboards can be customized at runtime. Using the Dashboard Organizer, invoked using the organise dashboard action, you can hide or show particular dashboard items as well as create new ones:

    Dashboard Organizer

     

    Don’t forget though, that the dashboard layout customization is still available in Win application.

    Switching Dashboards Via ViewVariants

    You can easily switch between several dashboards using the ViewVariants feature – just create several view variants in the Model Editor:

    Dashboard Switch

     

    And, of course, all of these improvements are available in Web applications as well.

    Displaying The Chart Bound to a PivotGrid

    We’ve implemented a feature whereby it is now possible to show the Chart, together with the PivotGrid. The Chart is bound to the PivotGrid, so the Chart contents changes depending on the selection you made in the PivotGrid:

    Pivot With Chart

    PivotWithChart

    Also, using the chart options, you can select whether to show row and column totals or not:

    PivotChartOptions

     

    ChartListEditor Improvements

    Web Chart Resizing

    One small improvement, but one that has a big impact, is that the ASPxChartListEditor is now able to adjust its size dynamically to fit the page during resizing.

    KPI Improvements

    If your KPIs have range comparisons, it is now possible to display sparkline graphs for both current and previous ranges:

    KPI - Sparkline graph

    Well that’s all for this whistle stop tour of some of the miscellaneous improvements we’ve made in XAF, until next time, happy XAF’ing! Smile

  • XAF – Filtering Improvements (Coming in V2010 Vol 2)

         

    In 10.2 we’ve re-written a lot of the XAF internals and as a result, we now have complete support for function criteria operators in all areas of XAF; for example, when specifying criteria for reports (FilterString property), List Views (SetFilterAction, ListView.Criteria property), KPI criteria, CriteriaEditor, Analysis objects, etc. And the best part? Since it is the internal components that were rewritten, there should not be any breaking changes! You can simply start using function criteria operators anywhere you need. Smile

    It’s all pretty straight forward, perhaps the only area where it’s a little tricky is where we implemented support for function criteria operators in built-in validation rules

    You can already use criteria operators when specifying criteria for the vast majority of built-in validation rules. The only exceptions are the RuleRange and RuleValueComparison validation rules. For compatibility reasons we have decided to introduce a new mode of operation for these rules. Now the rule constructors can take an additional mode parameter specifying how other parameter values are treated. If the parameter value is ParametersMode.Expression then criteria strings are treated as expressions and you can use criteria operators. If the parameter value is ParametersMode.Value then criteria strings are treated as strings and you can use read-only parameters. Here’s an example of what I mean:

    In 10.1, if you want to declare a rule using the CurrentDate read-only parameter you would write something like this…

    [RuleValueComparison("MyRule1", DefaultContexts.Save, ValueComparisonType.LessThan, "@CurrentDate")]

    Now it 10.2 you’d can use the LocalDateTimeToday function criteria operator like this…

    [RuleValueComparison("MyRule1", DefaultContexts.Save, ValueComparisonType.LessThan, "LocalDateTimeToday()", ParametersMode.Expression)]

    Here’s another example:

    In 10.1, using WeekAgo and CurrentDate:

    [RuleRange("MyRule2", "Save", "@WeekAgo", "@CurrentDate")]

    And in 10.2 using AddDays and LocalDataTime:

    [RuleRange("MyRule2", "Save", "AddDays(LocalDateTimeToday(), -7)", "LocalDateTimeToday()", ParametersMode.Expression)]

    As you can see, function criteria operators are much more powerful and flexible than read-only parameters. If you are thinking that the mode parameter looks a little odd then don’t worry, in the future, when we completely abandon XAF parameters, we will probably remove the mode parameter in these validation rules. Smile

    But what about transitioning from read-only parameters to criteria operators I hear you ask? We had about a dozen read-only operators available out of the box and here are some examples of possible transitions…

    To transition from CurrentUserIdParameter use the new CurrentUserId custom function criteria operator available in all XAF applications and to transition from CurrentDateTimeParameter use the standard LocalDateTimeNow function criteria operator. Now transitioning from WeekAgoParameter is a little more tricky as there is no such standard function criteria operator to replace it with. Instead the parameter should be rewritten as an expression, like so: AddDays(LocalDateTimeToday(), -7).

    If you find yourself frequently using the WeekAgoParameter, and do not want to type the expression over and over, you can implement a custom function criteria operator like so:

    using DevExpress.Data.Filtering;
    
    public class WeekAgoOperator : ICustomFunctionOperator
    {
        public string Name
        {
            get { return "WeekAgo"; }
        }
    
        public object Evaluate(params object[] operands)
        {
            return DateTime.Today.AddDays(-7);
        }
    
        public Type ResultType(params Type[] operands)
        {
            return typeof(DateTime);
        }
    }

    As you can see, writing a custom function criteria operator is just as straightforward as writing a custom read-only parameter. Custom criteria operators have an advantage however, they can take operands. So, while a read-only parameter can only return some value, a criteria operator value can be calculated based on the operand values.

    To use a custom function criteria operator, you need to register it. This can be done, for example, in a custom module:

    public override void CustomizeTypesInfo(DevExpress.ExpressApp.DC.ITypesInfo typesInfo) {
        base.CustomizeTypesInfo(typesInfo);
    
        XafTypesInfo.XpoTypeInfoSource.XPDictionary.CustomFunctionOperators.Add(new WeekAgoOperator());
    }

    After registering a criteria operator, you can use it anywhere you need. For example, you can create a List View filter via the Filter Action, that will use your operator, to, say select only the objects that were shipped within the last seven days:

    ShippingDate > WeekAgo()

    So to sum up, we now recommend that you use criteria operators instead of read-only parameters, because:

    1. They are easier to work with as there are a lot of predefined operators – actually about ten dozen - such as LocalDateTimeAfterTomorrow or Replace (See Criteria Language Syntax and FunctionOperatorType Enumeration). So, in most cases you can save yourself some time by not having to implement a read-only parameter and register it.
    2. They are more flexible since they can take operands, and so you can implement some really smart logic in an operator.
    3. Unlike read-only parameters, which by their nature are always evaluated on the client side, certain criteria operators can be evaluated on the server side. And this means better performance.

    Well that is all from this post, until next time, happy XAF’ing Smile

  • XAF – Detail View Performance Improvements (Coming in V2010 Vol 2)

         

    Are you working on XAF Windows Forms applications? Do you have complex Detail View forms? You know, ones with lots of tabs? You do? Cool, well in v2010 vol2 we have optimized the process of layout generation of these Views.

    Although this is a great improvement, we have provided an option - XafApplication.DelayedViewItemsInitialization, to enable it and it is turned off by default. Ha ha, gotcha! No seriously, the reason we have turned if off by default, is because to make this work we had to slightly change the old behaviour, so we need you to explicitly say you want to use this “power up”.

    Okay, let’s dive into the core of the optimization. As you already know, this feature is based on providing a lazy initialization of View items when a View is created (you may want to check out the following help topic to better understand how these elements relate to each other). Note that starting from 10.2, even if the optimization is turned off, the Frame and View for our ListPropertyEditor, DetailPropertyEditor and DashboardViewItem editors are initialized, not in the IComplexPropertyEditor.Setup method, but at the moment the respective items are added into the View. Though this change should not affect the order of related events and methods, we recommend you check your applications, you know, just in case… Smile.

    When the optimization is turned on, controls corresponding to View items will not be created right after the root control of the View is created. Instead, they will be created only once they are visible to end-users (same with items hidden in the layout Customization Form). This was made possible with the help of a change to the XtraLayout control in 10.2. Complex property editors, will also create their Frame and View only when their respective controls are created. Since their Frame, View and Control properties are null before the editors are visible, that leads to a potential problem in your code. For example, you should ensure that code in your controllers and custom ProprertyEditors is not accessing the above properties before the controls are created.  In order to bypass any possible problems, you should handle the ControlsCreated event of the required View item or test whether properties accessed are null. It is also possible that, in the future, we will provide an event when a View item is created to make it easier to handle this scenario.

    We won’t stop there though when it comes to improving the performance of XAF applications. We also plan to make improvements on the level of the XtraLayout control itself. There are also similar plans with regard to XAF ASP.NET applications. You can find links to related suggestions in this SC ticket.

    That’s all for this post, until next time, happy XAF’ing! Smile

  • XPO - N-Tier, Instance/Field-level Security And Much More in XPO (Coming in v2010 vol 2)

         

    Psst, hey you! Yes you… can you keep a secret? You can? Good. Remember we said in our 2010 Roadmap

    “The same goes for improvements to security: we shall be adding enough support for the security scenarios needed for XAF in the first part of the year, which will be fleshed out for other scenarios in the second.

    Instance and field-level security will be made available in the second half of the year, building on the implementation in XPO from the first half.”

    Well I have some news on that front. Coming in 2010.2 there will be some “undocumented features” to help support these required scenarios and I’ll let you in on the secret, if you promise not to tell the team that I told you. Winking smile

    We’ve added a new interface, IObjectLayer, the main implementer of this which is SimpleObjectLayer which serves as a bridge between the Session and the IDataLayer. To facilitate this, Session now has a new constructor which takes an implementer of IObjectLayer, in this case SimpleObjectLayer. The old constructor, which took an IDataLayer, still remains but this just creates a SimpleDataLayer for use with the Session, so we’ve maintained compatibility with your legacy code. Here’s a small example of what I’m talking about. Both the constructors in the example below, create a new UnitOfWork with a SimpleObjectLayer…

    public void Example()
    {
        //Get the data layer
        IDataLayer dataLayer = XpoDefault.GetDataLayer(connectionString, AutoCreateOption.DatabaseAndSchema);
    
        //Create a new unit of work, passing in a SimpleObjectLayer
        using (UnitOfWork uow = new UnitOfWork(new SimpleObjectLayer(dataLayer)))
        {
            //Do work with the objects
        }
    
        //SimpleObjectLayer created inside the constructor
        using (UnitOfWork uow = new UnitOfWork(dataLayer))
        {
            //Do work with objects
        }
    }

    Going forward, the changes we’ve made mean that the source of a Session need not only be a database, but can now be other sessions. To facilitate this we have created an Object, SessionObjectLayer, which will turn any UnitOfWork into a NestedUnitOfWork, like so…

    using(UnitOfWork uow = new UnitOfWork(dataLayer)) {
        
        //Create a Person object
        Person person = new Person(uow);
        person.Name = "Thomas Anderson";
        person.Age = 27;
        
        //Save it
        uow.CommitChanges();
        
        //Create a nested UnitOfWork using the new SessionObjectLayer
        using(UnitOfWork nestedUow = new UnitOfWork(new SessionObjectLayer(uow))) {
            
            //Load the Person object by key in a nested UnitOfWork
            Person personNested = nestedUow.GetObjectByKey<Person>(person.Oid);
            
            //Change it
            personNested.Age = 35;
            
            //And save to the basic UnitOfWork
            nestedUow.CommitChanges();
        }
    
        //Check that the object has changed in the basic UnitOfWork
        System.Diagnostics.Debug.Assert(person.Age == 35);
        uow.CommitChanges();
    }

    The next step is to serialise objects between a basic and a NestedUnitOfWork. To do this, we created two classes SerializableObjectLayerClient and SerializableObjectLayer, which behave like they are two halves of a SessionObjectLayer object. Meaning that the data that is sent between them, via ISerializableObjectLayer, can be serialised. This means our previous example, becomes…

    using(UnitOfWork uow = new UnitOfWork(dataLayer)) {
        
        //Create a Person object
        Person person = new Person(uow);
        person.Name = "Thomas Anderson";
        person.Age = 27;
        
        //Save it
        uow.CommitChanges();
        
        //Create a serialized ObjectLayer
        ISerializableObjectLayer sol = new SerializableObjectLayer(uow);
        
        //Create a client of serializable ObjectLayer
        IObjectLayer ol = new SerializableObjectLayerClient(sol);
        
        //Create a nested UnitOfWork
        using(UnitOfWork nestedUow = new UnitOfWork(ol)) {
                
            //Load the Person object by key in a nested UnitOfWork
            Person personNested = nestedUow.GetObjectByKey<Person>(person.Oid);
            
            //Change it
            personNested.Age = 35;
            
            //And save to the basic UnitOfWork
            nestedUow.CommitChanges();
        }
    
        //Check that the object has changed in the basic UnitOfWork
        System.Diagnostics.Debug.Assert(person.Age == 35);
        uow.CommitChanges();
    }

    Of course, the instance of SerializableObjectLayer can be anywhere, on another process, or even on another machine and you can access it via WCF, Remoting or any data transmission technology of your choice. This means that, at last, it is possible to build more complex N-tier systems using XPO! Smile

    It also enables a couple of different scenarios. Firstly, thin clients can push complex validation onto a server and simply load the processed objects. Secondly, it enables the long awaited field level and object instance security as the SessionObjectLayer object has a number of options that allow you to implement specific object processing – such as filtering – based on rules for loading and saving. Lastly, you can write a custom implementation of IObjectLayer which would allow you to write a wrapper for other ORMs.

    So why’s this stuff going to be undocumented in 10.2? Well it’s because these changes are really there to support the upcoming rewrite of XAF’s security system. As we stated in comments to previous blog posts, this rewrite will not be completed in the 10.2 timeframe so we decided to leave these XPO features undocumented at this time. So remember, no telling the team that I spilled the beans. Winking smile

    Well that’s all for this post, until next time, happy XPOI’ing Smile

    UPDATE: XPO – 11.1 Sneak Peek - WCF services for IObjectLayer

More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.