eXpress App Framework Team

This Blog

News

You are welcome to test the new XAF features prior to the 17.2 release: one, two, three, four, five, five

December 2011 - Posts

  • Take a tour of DXv2: XAF Q&A

    A bit late with this post,…but

    Check out the "Take a tour of DXv2: XAF” webinar as well as the "XAF - Application Server & Improved Security System" tutorial videos to get started with the newest version of the eXpressApp Framework (XAF).

    And don’t forget to check out the What’s New pages for both XAF and XPO:

    Finally, do not miss the new and updated help articles for these products located in the What’s New in Help document.

    I also wanted to answer a few of the more interesting questions left unanswered from our last webinar. So, here we go:

    Q: What are the main advantages of your application server and the improved security system? Why would one want to use them?
    A: In our opinion, every serious application for a medium or large enterprise requires a stable and solid security system that will ensure that clients only access data and perform operations they have permissions to. In the most cases, secure data filtering is done in the middle tier, thus preventing the client application from direct database connections. The client application usually connects to the middle tier server via Remoting, WCF or other popular data transport technologies. The middle tier application itself can be run as a console, Windows service application or be hosted as part of a web application on IIS.

    As you know, implementing, testing and maintaining even the core of such a system yourself will require enormous resources. Implementing GUI for it will also cost you a lot of time and money. In addition, if you Google the term, you will quickly find that it will require learning both a large number of technologies and numerous patterns & best practices available in papers created by Microsoft and many third-parties…

    With XAF you get all of this out-of-the-box and as a result you have a ready GUI + Core that is based on existing DevExpress technologies (we use DevExpress visual components for the UI and XPO for the application server and security core). Finally, note that the XAF security system supports defining permissions on the object type, object instance and member levels, as well as custom permissions.

    Q: What are the main difference between the old and new XAF security systems?
    A: The new XAF security system prevents client applications from retrieving sensitive data. All permission requests are redirected to the security service located on the application server. Your secure data is much safer now as it will not leave the server. Refer to this help article explaining these differences in greater detail. In addition, the new security system is accompanied with a more effective UI for editing security permissions – you now have a permissions matrix that I believe will be welcomed by your clients.

    Q: I am interested in the new application server & security system and just wanted to verify that if a user does not have permissions to an object / field, the respective information will not be displayed in reports, analysis, etc.
    A: Of course, it works as you would expect and these features were specially designed for these scenario. Security does restrict data on the server side so that it never appears in reports, analysis and elsewhere on the client side. For more information, check out the work schema. Note that to obtain all these benefits, you will need to configure security in the middle tier. Simply using the new security system (without implementing it in the middle tier) will not provide data filtering on the server side, because this is done by the middle tier service.

    Q: Does your new security system allow creating and plugging custom security permissions, i.e. not only permissions for business objects and their members? How do I implement a custom permission?
    A: Sure, much like the previous version, our new security system allows for this. A good example of a custom permission is “Edit Model" permission. Refer to the following Support Center ticket for a detailed description and a small sample project that demonstrates its implementation: http://www.devexpress.com/issue=Q358567

    Q: Is it necessary to host the application server on a separate machine as part of a console, Windows service application or a web application on IIS?
    A: No, it is absolutely unnecessary. The application server is a pure NET code that can be run anywhere you need, even on the client application. For instance, in our SecurityDemo, the application server is hosted in the same client application, but in a different AppDomain (check the ApplicationServerStarter class for the details). By default, we provide a Visual Studio Project Template that hosts the application server in a Windows service. We plan to provide additional templates based on the customer feedback. If you cannot wait, it is not difficult to make these templates yourself based on the defaults we provide – it is simply a matter of creating a corresponding application type (refer to MSDN for more details) and copying the required application server code.

    Q: Is there a way to encrypt or compress data between the application server and the client?
    A: There is no special XAF encrypting code because everything is already supported by underlying data transport technologies. For instance, refer to the  http://msdn.microsoft.com/en-US/library/k62k71x0(v=VS.80).aspx and http://msdn.microsoft.com/en-us/library/ms735093.aspx help articles to learn more.

    Q: Is Application server completely stateless?
    A: Yes, the application server is stateless. However, the server caches a database session and access rights for a particular client. It's not a long-living cache and this is not a state for the client application.

    Q: I heard that you are also planning to move some standard XAF functionality (audit trail, validation, etc.) to the server side, what if I also want to execute my business rules on the server? How do I proceed?
    A: Yes, you are right, we have such plans for the future. In the meantime, if you want to delegate business logic from the client to the server, you can implement a solution similar to that demonstrated in the following Support Center ticket: http://www.devexpress.com/issue=Q356933

    Q: Is there an easy and fast way to replace the old security system with new member-level security?
    A: Yes, we'll provide a sample converter that can be used to convert old permissions to new permissions for our built-in security objects (User, Role, SecuritySimple, SecurityComplex, etc.). I suggest you check out this discussion in the Support Center for more information.

    Q: I noticed there were still some postbacks during my Web application operation. Is it a bug?
    A: No, some tasks can be performed only via postback (e.g. file download, theme changes, etc.). However, we plan enhance our Web UI and you can see our plans in this blog post.

    Q: I like the new AJAX Web UI, but previously I used some custom user and third-party controls that operate via postbacks. Is it possible to force them to use AJAX as well?
    A: If a third-party control operates via postbacks and does not support AJAX itself, it's unlikely to switch it into AJAX. However, it will continue to operate via postbacks as before. As for your custom user controls, it is possible to convert them to AJAX-like controls. Please contact our Support Team for further instructions.

    Q: What is the best way to convert my existing Web application to 11.2 to use the improved AJAX functionality?
    A: As always, we recommend that you follow the instructions given in the Upgrade Notes help article. From this article you can also find links to the list of breaking changes and implemented features. Finally, we suggest you check out the eXpressApp Framework v11.2 ASP.NET Application Migration Guidelines we've prepared. If you experience any difficulties with the upgrade, feel free to contact our Support Team.

    Q: Do you provide any converter for rules created using obsolete ConditionalEditorState and ConditionalFormatting modules?
    A: Sure, we do. Please refer to the following KB Article: http://www.devexpress.com/kb=K18547.

    Q: What are your plans for the old security system? I also noticed that not all XAF demos migrated to the new security system.
    A: Yes, that is true about the demos. You might also notice that the old security is still described in docs. We decided not to migrate all demos to the new security system in this release because there are a lot of people who are using the old security and might even use it in the future as it is effective, even though it works at the UI level. However, migrating all our demos to the new security system is planned as well as complete replacement of the old security system. People who are using Domain Components can also track this suggestion – a DC-based demo based on the new security system.

    As always, we will also try to keep new videos, blogs and other training materials coming. If you have specific suggestions or just want to share your feedback on how we are doing, please drop us a line or simply email me at dennis@devexpress.com.

    Happy XAFingSmile

  • LINQPad is XPO’s new best friend!

    LINQ is .NET Language-Integrated Query. It's included in .NET Framework 3.5 and you can use it in Visual Studio 2008 projects. XPO has officially supported LINQ since v7.3 and since then we have continued to improve and support it. Nowadays LINQ to XPO is very mature, extendable (How to: Implement Custom Functions and Criteria in LINQ to XPO) and powerful (Free Joins). In the latest version we make it even easier to use LINQ to XPO since we only distribute one assembly, DevExpress.XPO.dll, which includes everything! (custom providers as well).

    XPO can talk transparently to a large list of database systems. It was already possible to make complex queries using our standard criteria syntax, however using LINQ offers some great advantages.

    1. No magic strings, like you have in standard criteria syntax,
    2. Intellisense support making it easier and faster to construct your queries,
    3. Compile time checking,
    4. Learning to write LINQ queries/lambdas is a must learn for .NET developers,

    The benefits are clear, however there is a caveat when using LINQ. It is not possible to use Edit and Continue and with even the smallest change you need to restart your debugging session. As a result your development speed is decreased dramatically.

    The solution as always is to use the right tool and in this case the right tool is LINQPad. It provides a flexible UI allowing you to use LINQ in various ways.

    In our latest version our team released an XPO context driver for LINQPad. Let’s see how to configure it.

    Firstly we need to install the driver found at C:\DevExpress 2011.2\Components\Tools\DXperience\XPOContextDriver.lpx.

    image

    Secondly we need to setup a new connection.

    image

    In this example we are going to use the MainDemo assembly containing the business objects.

    image

    LINQPad populated the domain in a hierarchical treelist. This allows us to enjoy using drag & drop plus intellisence in its expression editor to form the LINQ queries. Furthermore it is possible to use your style of language as demonstrated below.

    image

    The cool part is that LINQPad, written by the great Joe Albahari, is available for free. It is strongly recommended as a great way to learn LINQ.

    Now for the fun part, let’s see it in action. Imagine we have the following code in our VS.

    var queryable = from c in contacts

                    let tasks = c.Tasks.Where(t => t.ActualWork < 0)

                    where tasks.Any()

                    orderby c.LastName

                    select new {

                                   c.LastName,

                                   Orders = tasks.Count(),

                               };

     

    We wish to see the results of queryable variable ,the best way to achieve this is to set a breakpoint then hit F5. Next we wait for our app to load and navigate to the action that will hit the breakpoint. Finally we must select the queryable variable and hit Shift+F9 to invoke the debugger window and examine the result set. Now we can try to make our requirements more complex. Lets say we also want to examine the result set when ActualWork>10. The solution is really easy when using LINQPad, we simply need to copy paste the code from VS to LINQPad the expression editor like this,

    image

    After this we can quickly and easily form queries as we wish and examine their result sets instantly. Using the excellent and cheap LINQPad Autocompletion it is possible to use VS like intelligence to further speed up your development.

    image

    PS: eXpandFrameWork contributors are already using the Autocompletion feature since LINQPad offered a license for its contributors.

    We would appreciate your feedback on this post. Has it been useful to you? Feel free to contact us with any further questions

  • eXpand on Hanselminutes

    First of all I would like to say a big thank you to Scott for having me on his show. I really enjoyed our conversation even though they said I worked for one of our competitors in the intro!

    Framework Series: The eXpand Framework with Apostolis Bekiaris

    For those of you who have not had a chance to listen to the show yet Scott and I had an illuminating discussion about the benefits of open source. I found the comments Scott made about Microsoft’s attitude towards these kind of projects particularly revealing. Of course we found plenty of time to chat about eXpand, including some of the history of the project and the important role that our contributors play. It is clear that Scott recognizes the value of a healthy open source community like ours. Also on the agenda  were the advantages of the special relationship between XAF and eXpand as well as the support that DevExpress gives to the world of open source.

    Thanks again to all of you out there in the community this is your framework and we all deserve a share of the glory!

  • Hey Mom we are on the Hanselminutes show!

    At 11.00 PST on Thursday 15th December I will be appearing live on Scott Hanselman’s podcast Hanselminutes. During the course of the show Scott and I will be discussing eXpand framework and its relationship with XAF. Please tune in and show some support for your favorite frameworks! We built this thing together guys and this is an exciting event for all of us.

  • You have changes? I have Workflow!

    Let me describe for a moment how we at DevExpress work. We build and sell software which means that we only sell and provide support for products that have been built and tested by us! However I am here as a framework evangelist and huge XAF fan. This makes it my duty to spread the word as much as I can and make XAF even bigger. To this end through collaboration within the XAF community, we have been building and supporting eXpand. This framework follows XAF to the letter and takes things even further. eXpand gets its inspiration from real life situations and bases itself on examples from DevExpress Support Center. eXpand is the first open source project based on the DevExpress eXpressApp Framework (XAF). More info is available at www.expandframework.com and our very existence relies on your efforts! Anyone is welcome to contribute and enjoy the rewards. It is not necessary to be a XAF guru, we can all manage to create a behavior taken from DevExpress code central. Let’s work together to enhance our beloved XAF!

    WF4 uses a service oriented architecture and as a result any problem can be decoupled into smaller, easily solvable and testable services. XAF uses MVC architecture which, in a sense, is very similar to that used by WF4. We can compare XAF’s controllers to WF4 services. Moreover XAF’s Application does the same job as the WF4 server. The upshot of all this is that users should be able to get the feel of WF4 in no time at all. The XAF workflow module introduces a new layer that makes the already decoupled services aware of our business classes.  After this the sky is the limit and over the next few posts I aim to demonstrate some of what can be achieved. For example the next post will focus on creating an event driven workflow initialization engine.

    To get back to today’s post, we will discuss an implementation that is very decoupled and as a result it has very limited dependencies on other modules. It is worth noting that all XAF’s features are decoupled, persistent objects take on the role of domain mappers.

    Take these requirements;

    • an end user needs to be able to input an object type (and or) a property name,
    • an object change needs to start the workflow either at client or at sever,
    • workflows need to be aware of the object that has changed, its PropertyName and its property OldValue.

    The custom workflow definition

    We cannot use the default XAF XpoWorkFlowDefinition class in any way.  This is because there are no fields to store the PropertyName and its OldValue. We should not even derive from the default XpoWorkFlowDefinition because we may face difficulties as this class is used by our workflow server. To cope with this issue it is necessary to create a custom ObjectChangedWorkflow definition as shown.

    image

    While we are doing this we also need to modify the default xaml of the workflow and add the two more arguments (propertyName, oldValue) as per our requirements.

    image

    Below you can see the UI of this custom workflow definition,

    image

    Up to here XAF has made things very straightforward for us. We have designed a normal persistent class to store our data and we have used attributes (PropertyEditorType, DataStourceProperty, TypeConverter etc) to configure the UI.

    Registration of custom workflow definition

    The next step is to register this custom workflow definition. To help with this task, eXpand, provides the WorkflowStartService<T> where T is the type of workflow. Furthermore for ObjectChangeWorkflow definitions the implementation is rather easy since there are no further requirements.

    public class ObjectChangedWorkflowStartService : WorkflowStartService<ObjectChangedWorkflow> {

        public ObjectChangedWorkflowStartService()

            : base(TimeSpan.FromMinutes(1)) {

        }

        public ObjectChangedWorkflowStartService(TimeSpan requestsDetectionPeriod) : base(requestsDetectionPeriod) { }

        protected override bool NeedToStartWorkflow(IObjectSpace objectSpace, ObjectChangedWorkflow workflow) {

            return true;

        }

     

        protected override void AfterWorkFlowStarted(IObjectSpace objectSpace, ObjectChangedWorkflow workflow, Guid startWorkflow) {

     

        }

    }

    Start workflow - Track Object Changes

    Now, when I have registered workflows on the server, it's time to return to my task: start a workflow when a property has been changed.
    In XAF, I can track changes with the help of the ObjectSpace.Committing and ObjectSpace.ObjectChanged events. However because we need to create only one request per object change, it is advisable to collect the changes in an array.

    protected override void OnActivated() {

        base.OnActivated();

        if (TypeHasWorkflows()) {

            ObjectSpace.ObjectChanged += PopulateObjectChangedEventArgs;

            ObjectSpace.Committing += StartWorkFlows;

        }

    }

     

    void PopulateObjectChangedEventArgs(object sender, ObjectChangedEventArgs objectChangedEventArgs) {

        if (!string.IsNullOrEmpty(objectChangedEventArgs.PropertyName)) {

            var changedEventArgs = _objectChangedEventArgses.FirstOrDefault(args => args.Object == objectChangedEventArgs.Object && args.PropertyName == objectChangedEventArgs.PropertyName);

            if (changedEventArgs != null) {

                _objectChangedEventArgses.Remove(changedEventArgs);

                _objectChangedEventArgses.Add(new ObjectChangedEventArgs(changedEventArgs.Object, changedEventArgs.PropertyName, changedEventArgs.OldValue, objectChangedEventArgs.NewValue));

            } else

                _objectChangedEventArgses.Add(objectChangedEventArgs);

        }

    }

     

    void StartWorkFlow(ObjectChangedEventArgs objectChangedEventArgs, ObjectChangedWorkflow objectChangedWorkflow) {

        var o = objectChangedEventArgs.Object;

        ITypeInfo typeInfo = XafTypesInfo.Instance.FindTypeInfo(o.GetType());

        object targetObjectKey = typeInfo.KeyMember.GetValue(o);

        if (objectChangedWorkflow.ExecutionDomain == ExecutionDomain.Server) {

            CreateServerRequest(objectChangedEventArgs, objectChangedWorkflow, targetObjectKey, typeInfo);

        } else {

            InvokeOnClient(objectChangedEventArgs, objectChangedWorkflow, targetObjectKey);

        }

    }

    As you will have noticed we have not used the default VS naming for ObjectSpace event handlers. This is because the names that have chosen give a more specific idea of how each method works.

    The ObjectChanged event occurs each time a property is changed and the changes are collected in the objectChangedEventArgses array. The Committing event occurs once changes are ready to be sent to the server and workflows start for each entry. We have introduced two options for starting and executing workflows;

    1. Execute synchronously and locally,
    2. Send a request to the server and execute at the server asynchronously

    Execute a workflow synchronously on the client

    The next stage is to create activities at the client then on ObjectSpace CommitChanges from appropriate WorkflowDefinition and execute them immediatelly

    public class StartWorkflowOnObjectChangeController : ViewController<ObjectView> {

     

        void InvokeOnClient(ObjectChangedEventArgs objectChangedEventArgs, ObjectChangedWorkflow objectChangedWorkflow, object targetObjectKey) {

            Activity activity = ActivityXamlServices.Load(new StringReader(objectChangedWorkflow.Xaml));

            var dictionary = ObjectChangedStartWorkflowService.Dictionary(targetObjectKey, objectChangedEventArgs.PropertyName, objectChangedEventArgs.OldValue);

            WorkflowInvoker.Invoke(activity, dictionary);

        }


    This is a simple code which can be found in nearly any WF4 example at http://www.microsoft.com/download/en/details.aspx?id=21459.

    Send a request to start workflow on the server

    The second of our two methods involves starting the workflow at the server. Now we need to notify the server of the values of those arguments as well. In the manually starting workflows post we learnt that XAF does this by using XpoStartWorkflowRequest. This class has a different design however, and may create issues since it is used by XAF default services. Therefore instead of deriving from XpoStartWorkflowRequest we need to design a similar custom class.

    public class ObjectChangedXpoStartWorkflowRequest : WFBaseObject, IObjectChangedWorkflowRequest {

     

        [TypeConverter(typeof(StringToTypeConverter))]

        public Type TargetObjectType {

            get { return _targetObjectType; }

            set { SetPropertyValue("TargetObjectType", ref _targetObjectType, value); }

        }

        #region IDCStartWorkflowRequest Members

        public string TargetWorkflowUniqueId {

            get { return GetPropertyValue<string>("TargetWorkflowUniqueId"); }

            set { SetPropertyValue("TargetWorkflowUniqueId", value); }

        }

     

        [ValueConverter(typeof(KeyConverter))]

        public object TargetObjectKey {

            get { return GetPropertyValue<object>("TargetObjectKey"); }

            set { SetPropertyValue<object>("TargetObjectKey", value); }

        }

        #endregion

        #region IObjectChangedWorkflowRequest Members

        public string PropertyName {

            get { return _propertyName; }

            set { SetPropertyValue("PropertyName", ref _propertyName, value); }

        }

     

        [ValueConverter(typeof(SerializableObjectConverter))]

        [Size(SizeAttribute.Unlimited)]

        public object OldValue {

            get { return _oldValue; }

            set { SetPropertyValue("OldValue", ref _oldValue, value); }

        }

    This is a very simple class, its only role is to store values in the database. Now instead of invoking workflows locally we only need to create ObjectChangedXpoStartWorkflowRequest objects.

    public class StartWorkflowOnObjectChangeController : ViewController<ObjectView> {

        void CreateServerRequest(ObjectChangedEventArgs objectChangedEventArgs, ObjectChangedWorkflow objectChangedWorkflow, object targetObjectKey, ITypeInfo typeInfo) {

            var request = ObjectSpace.CreateObject<ObjectChangedXpoStartWorkflowRequest>();

            request.TargetWorkflowUniqueId = objectChangedWorkflow.GetUniqueId();

            request.TargetObjectType = typeInfo.Type;

            request.TargetObjectKey = targetObjectKey;

            request.PropertyName = objectChangedEventArgs.PropertyName;

            request.OldValue = GetOldValue(objectChangedEventArgs);

        }

    In the next step we are going to create a service to consume these values from the server and start a workflow,

    public class StartWorkflowOnObjectChangeService : BaseTimerService {

        public override void OnTimer() {

            using (var objectSpace = ObjectSpaceProvider.CreateObjectSpace()) {

                //get all requests from the database

                foreach (var request in objectSpace.GetObjects<ObjectChangedXpoStartWorkflowRequest>()) {

                    //find workflow

                    var definition = GetService<IWorkflowDefinitionProvider>().FindDefinition(request.TargetWorkflowUniqueId);

                    if (definition != null && definition.CanOpenHost) {

                        //Start the workflow passing in PropertyName && OldValue

                        if (GetService<ObjectChangedStartWorkflowService>().StartWorkflow(definition.Name,

                            request.TargetWorkflowUniqueId, request.TargetObjectKey, request.PropertyName, request.OldValue)) {

                            objectSpace.Delete(request);

                            objectSpace.CommitChanges();

                        }

                    }

     

                }

            }

        }

    At this point our server has all the information it needs to start workflows with arguments taken from persistent ObjectChangeXpoStartWorkFlowRequest objects.

    I must admit that I have fully enjoyed preparing this post. The decoupled development experienced offered by the WF service oriented model is something that really appeals to me. At the same time XAF’s workflow module implementation made modeling the requirements a simple and enjoyable process. As usual it was possible to work directly on the problem and leave the hard work to non XAF developers.

    We are happy to read your feedback about this!. Remember that your questions are the best candidates for future posts

LIVE CHAT

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 info@devexpress.com or call us at +1 (818) 844-3383

FOLLOW US

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