OBSOLETE - How to deploy the OData security service in the Cloud for further use by a mobile DevExtreme client

XAF Team Blog
12 December 2012

UPDATED

This article is obsolete and we no longer provide any support on its content.

Instead,  refer to the XAF Goes Mobile: CTP Version Ships with v15.2.9 post.

==================================================


In this blog post, we’ll use the new DXTREME HTML JS framework to create a phone web app that works on iOS and Android devices. You can DOWNLOAD a working version of this app here (DXperience Universal 12.2.4 is required). Please do not miss a gentle disclaimer in the end.

1. Mobile Client Considerations

Let’s start with an XAF application already connected to the built-in middle-tier security service via WCF or .NET Remoting. It may look like this:

Contacts

If you have an existing XAF app and want to connect it to the security service, you can change the application connection string to a service URL, e.g.:
http://samplexafsecurity.cloudapp.net/CustomWcfSecuredDataServer.svc

Once the XAF application is connected to the security service, the built-in Security module will handle user authentication, data filtering and UI modifications as needed, according to specified security permissions. However, we need to extend the capabilities delivered by the built-in module to handle more specific security scenarios, such as:

    Is user X permitted to use this app?
    Is user X permitted to perform operation Y on data record Z?
    Is user X allowed to read member Y for data record Z?

    We can handle all of these scenarios with a custom authentication service.

    Before we start, we should think about the way we want to transfer data to our clients. Because of the wide variety of client platforms, we need protocol that allows interoperability across all the platforms and devices we want to support. OData is a great candidate. Another great choice would be DXTREME, which supports iOS, Android, Win8 and other operating systems, without forcing us to dig into the framework of each individual platform.

    Finally, we will deploy our authentication service to Windows Azure. Let’s get started!

    2. Database in the Cloud

    Note: These instructions apply to Windows Azure, but other cloud providers have similar capabilities. A quick Google search shows this is true for Amazon (btw, I recommend this blog if you are thinking about moving your XAF Web app to Amazon).

    Let’s start by launching the Azure portal. Click the SQL Databases tab and then click Create an SQL Database. Specify the necessary parameters:

    NewDB

    Note we did not specify an existing database server - we will create a New SQL Database Server.

    Next we need to fill in the SQL Server administrator credentials and specify its physical location. We will also need to create tables and provide some initial data. To make that easier, we have prepared the Azure_XAF_AuthenticationDemoDB.sql file, which is a part of the DBCreator project in this example. To use this file, we will need to locate the TestDB database created above and click the MANAGE button at the bottom: 

    ManageDB

    Click Open and provide a path to the SQL file (.\Utils\DBCreator\Azure_XAF_AuthenticationDemoDB.sql):

    OpenSQL

    Opening this file will create the required database and tables. Next we need to populate these tables with some test data using the DBCreator project mentioned earlier. It just needs an updated connection string from our Azure portal. Place the connection string in the .Utils\DBCreator\app.config file. It should look something like this:

    "User ID=test;Password=***;Pooling=false;Data Source=***.database.windows.net;Initial Catalog=TestDB"

    With the connection string specified, we can run the DBCreator console app:

    updateDB

    Running DBCreator does the following:

      Creates three users in the SecuritySystemUser table: one with unlimited rights (Admin) and two regular users (Sam and John). All users have empty passwords for the demo.
      Adds a few contacts corresponding to these users to the Contact table
      Creates security permissions so sample users can view all contacts, but only be able to edit their personal contacts.
      Creates a custom permissions set for the “Advanced User” contact. By default Sam and John can view only Photo and First Name fields; remaining fields are hidden.

      Code for creating permissions is not included in this article, however it is easily discoverable in the attached example.

      3. A WCF Middle-Tier Security Service

      Once our work with the database is complete, we can begin work on the most interesting part of this article – the creating and deploying of a service in the cloud! Let’s begin with using the Empty Web Application project template to create our service application called ClientServer_Wcf_CustomAuth.Service.

      NewWebApp

      The next step is to add a new WCF service called CustomWcfSecuredDataServer using the built-in command under the context menu invoked for the created project in the Solution Explorer. This will result in Visual Studio generating CustomWcfSecuredDataServer.svc and ICustomWcfSecuredDataServer.cs files. We will remove the latter file as it is not needed. The next step is to replace the base class for the CustomWcfSecuredDataServer class with the WcfSecuredDataServer.

      namespace ClientServer_Wcf_StandartAuth.Server {
      
          [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
      
          [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, MaxItemsInObjectGraph = System.Int32.MaxValue, ConcurrencyMode = ConcurrencyMode.Multiple)]
      
          public class CustomWcfSecuredDataServer : WcfSecuredDataServer {
      
              private static SecuredDataServer securedDataServer;
      
              public static void SetSecuredDataServer(SecuredDataServer dataServer) {
      
                  securedDataServer = dataServer;
      
              }
      
              public CustomWcfSecuredDataServer() : base(securedDataServer) { }
      
          }
      
      }


       

      Next, we will add a Global.asax file using the built-in item template and modify its code as follows:


       

      namespace ClientServer_Wcf_StandartAuth.Server {
      
          public class Global : System.Web.HttpApplication {
      
              public static string ConnectionString;
      
              protected void Application_Start(object sender, EventArgs e) {
      
                  ConnectionString = ConfigurationManager.ConnectionStrings["AzureApplicationServices"].ConnectionString;
      
                  CustomAuthenticationServiceHelper customAuthenticationServiceHelper = new CustomAuthenticationServiceHelper();
      
                  ValueManager.ValueManagerType = typeof(ASPRequestValueManager<>).GetGenericTypeDefinition();
      
                  QueryRequestSecurityStrategyHandler securityProviderHandler = delegate() {
      
                      return new SecurityStrategyComplex(typeof(SecuritySystemUser), typeof(SecuritySystemRole), new AuthenticationStandard());
      
                  };
      
                  SecuredDataServer dataServer = new SecuredDataServer(
      
                          ConnectionString, customAuthenticationServiceHelper.XPDictionary, securityProviderHandler);
      
                  CustomWcfSecuredDataServer.SetSecuredDataServer(dataServer);
      
              }
      

      A final tweak will alter the web.config file to warn WCF about us transferring relatively large amounts of data to it (e.g., photos):

      <wsHttpBinding>
      
      <binding maxReceivedMessageSize="2147483646">
      
      <readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="2147483646" maxBytesPerRead="4096" maxNameTableCharCount="5242880"/>
      
      </binding>
      
      </wsHttpBinding>

       

      This concludes this step. You can always find more details in the source code of the ClientServer_Wcf_CustomAuth.Service project that hosts this service. It is not rocket science, and I believe that experienced XAFers noticed that the service code mimics what you can already find in the Application Server project template provided by XAF – here we just did things manually and used an ASP.NET application instead of the Windows Service or Console Application projects by default. Due to a heavy demand from our customers, we chose the ASP.NET application format as an example.

      4. Deploying the middle-tier security service in Azure

      By using the built-in Add Windows Azure Cloud Service Project command to create a new project titled the ClientServer_Wcf_CustomAuth.Service.Azure, we can easily deploy our newly-created security system in Azure.

      AddAzureCloudServiceProject_step1

      Please utilize the screenshots below to review the steps that follow.

      CSPPublish

      CSPPublish_step2

      CSPPublish_step3

      CSPPublish_step4

      CSPPublish_step5

      CSPPublish_step6

      Once all the above-mentioned steps have been completed, we can simply press the Publish button and wait for the service to begin so that we can ensure that things run smoothly via our Azure portal.
      Since everything operates correctly, we can now access our service at samplexafsecurity.cloudapp.net.

      5. An OData Service Consumed by Mobile and Other Non-XAF Clients

      Let’s begin by creating an empty Web project called CustomAuthenticationService. Next, we will add a class, which is derived from the base XpoDataServiceV3 class. (You may recall that it was added in XPO 12.2 to support the latest OData version.) Now we will add several service operation methods (IsGranted, IsUserAllowed, CanReadMembers) marked with the WebGet attribute to indicate that they are only used to retrieve information from the service, which will be REST by nature. Methods are required to implement a security on the client. 

      namespace CustomAuthenticationService {
      
          [JSONPSupportBehaviorAttribute]
      
          [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
      
          [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, MaxItemsInObjectGraph = System.Int32.MaxValue, ConcurrencyMode = ConcurrencyMode.Multiple)]
      
      
          public class CustomAuthenticationDataService : XpoDataServiceV3, System.Data.Services.IRequestHandler {
      
              private DataServiceHelper _dataServiceHelper;
      
              public CustomAuthenticationDataService()
      
                  : this(new HttpContextWrapper(HttpContext.Current)) {
      
              }
      
              public CustomAuthenticationDataService(HttpContextBase httpContext)
      
                  : this(httpContext, new CustomAuthenticationServiceHelper(), "CustomAuthenticationService") {
      
              }
      
              public CustomAuthenticationDataService(HttpContextBase httpContext, DataServiceHelper dataServiceHelper, string containerName) :
      
                  base(new MyContext(containerName, dataServiceHelper.NamespaceName, dataServiceHelper.CreateDataLayer())) {
      
                  if((httpContext == null) && (HttpContext.Current == null)) {
      
                      throw new ArgumentNullException("context", "The context cannot be null if not running on a Web context.");
      
                  }
      
                  _dataServiceHelper = dataServiceHelper;
      
              }
      
              public static void InitializeService(DataServiceConfiguration config) {
      
                  //config.SetEntitySetAccessRule("*", EntitySetRights.All);
      
                  config.SetEntitySetAccessRule("Contact", EntitySetRights.All);
      
                  config.SetServiceOperationAccessRule("IsGranted", ServiceOperationRights.AllRead);
      
                  config.SetServiceOperationAccessRule("IsUserAllowed", ServiceOperationRights.AllRead);
      
                  config.SetServiceOperationAccessRule("CanReadMembers", ServiceOperationRights.AllRead);
      
                  config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
      
                  config.DataServiceBehavior.AcceptProjectionRequests = true;
      
              }
      
              protected override void HandleException(HandleExceptionArgs args) {
      
                  if(args.Exception.GetType() == typeof(ObjectLayerSecurityException)) {
      
                      //Forbidden
      
                      args.Exception = new DataServiceException(403, args.Exception.Message);
      
                  }
      
                  base.HandleException(args);
      
              }
      
              [WebGet]
      
              public bool IsGranted(string objectType, string memberName, string objectHandle, string operation) {
      
                  Type type = XafTypesInfo.Instance.FindTypeInfo(objectType).Type;
      
                  return ((IRequestSecurity)SecuritySystem.Instance).IsGranted(new ClientPermissionRequest(type, memberName, objectHandle, operation));
      
              }
      
              [WebGet]
      
              public IEnumerable<string> CanReadMembers(string objectType, string membersName, string targetObjectsHandle) {
      
                  List<string> _membersName = new List<string>(membersName.Split(';'));
      
                  List<string> _targetObjectsHandle = new List<string>(targetObjectsHandle.Split(';'));
      
                  Type type = XafTypesInfo.Instance.FindTypeInfo(objectType).Type;
      
                  Dictionary<string, bool> canReadMembers = ((IRequestSecurity)SecuritySystem.Instance).CanReadMembers(type.AssemblyQualifiedName, _membersName, _targetObjectsHandle);
      
                  List<string> result = new List<string>();
      
                  foreach(KeyValuePair<string, bool> item in canReadMembers) {
      
                      result.Add(item.Key + ";" + item.Value);
      
                  }
      
                  return result;
      
              }
      
              [WebGet]
      
              public bool IsUserAllowed() {
      
                  return true;
      
              }
      
          }
      
      }


      This would be a good time to take a deeper look at this service.  As you can see, we limited access to the Contact business object when configuring the service:

      config.SetEntitySetAccessRule("Contact", EntitySetRights.All);

      This is a flexible solution for controlling what is accessible and what is hidden from service users. Error handling is provided by the HandleException method, which wraps ObjectLayerSecurityException into DataServiceException – a step required for providing a client application with meaningful error code. There are three primary exceptions: the DataServiceClientException for client operations (updates/inserts), the DataServiceQueryException for querying via LINQ and the DataServiceRequestException for requesting data via a URI. All other exceptions will be passed to the client as an “«Internal Server Error»” with the 501 code, which does not provide a lot of useful information in many cases.

      There are also a number of auxiliary classes that are required for the service to work.

      ·       The DataServiceHelper class is a helper that provides methods for accessing XAF IObjectSpaceProvider and XPO IObjectLayer entities.

      ·       The JSONPSupportInspector is required to provide jsonp support; you can learn more about it here.

      ·       The ASPRequestValueManager<ValueType> is required to store security system objects within the context of a current request.

      ·       MyContext is a descendant of the XpoContext base class.  We overrode the ShowLargePropertyAsNamedStream and HideProperty methods in this class to tell XPO to:

      -pass streams as a part of the query instead of the URL,

      -and to hide the Oid property of the Contact class.

      Once we are done with the XPO OData service, we will add the Global class using the respective item template. In this class, we will handle all the queries to our service using the means provided by the XAF security system. Let’s review the Application_AuthenticateRequest method, where we will check user credentials and request further processing.

      namespace CustomAuthenticationService {
      
          public class Global : System.Web.HttpApplication {
      
              public static string ConnectionString;
      
              protected void Application_Start(object sender, EventArgs e) {
      
                  ValueManager.ValueManagerType = typeof(ASPRequestValueManager<>).GetGenericTypeDefinition();
      
                  ConnectionString = ConfigurationManager.ConnectionStrings["AzureApplicationServices"].ConnectionString;
      
              }
      
              protected void Session_Start(object sender, EventArgs e) { }
      
              protected void Application_AuthenticateRequest(object sender, EventArgs e) {
      
                  SecurityStrategyComplex securityStrategy = new SecurityStrategyComplex(typeof(SecuritySystemUser), typeof(SecuritySystemRole), new AuthenticationStandard());
      
                  SecuritySystem.SetInstance(securityStrategy);
      
                  // Remember claims based security should be only be used over HTTPS
      
                  //if(context.Request.IsSecureConnection){
      
                  string userName = GetUserName(HttpContext.Current.Request);
      
                      if(string.IsNullOrEmpty(userName)) {
      
                          HttpContext.Current.Response.Status = "401 Unauthorized";
      
                          HttpContext.Current.Response.StatusCode = 401;
      
                          HttpContext.Current.Response.End();
      
                          return;
      
                      }
      
                      ((AuthenticationStandardLogonParameters)SecuritySystem.LogonParameters).UserName = userName;
      
                      ((AuthenticationStandardLogonParameters)SecuritySystem.LogonParameters).Password = GetPassword(HttpContext.Current.Request);
      
                  //}
      
                  CustomAuthenticationServiceHelper helper = new CustomAuthenticationServiceHelper();
      
                  try {
      
                      //Calling Cross Domain WCF Service using Jquery
      
                      // http://www.devexpress.com/Support/Center/Issues/ViewIssue.aspx?issueid=KA18633
      
                      string origin = HttpContext.Current.Request.Headers["Origin"];
      
                      if(!string.IsNullOrEmpty(origin)) {
      
                          HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin);
      
                      }
      
                      string method = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
      
                      if(!string.IsNullOrEmpty(method))
      
                          HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", method);
      
                      string headers = HttpContext.Current.Request.Headers["Access-Control-Request-Headers"];
      
                      if(!string.IsNullOrEmpty(headers))
      
                          HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", headers);
      
                      HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
      
                      if(HttpContext.Current.Request.HttpMethod == "OPTIONS") {
      
                          HttpContext.Current.Response.StatusCode = 204;
      
                          HttpContext.Current.Response.End();
      
                      }
      
                      SecuritySystem.Instance.Logon(helper.ObjectSpaceProvider.CreateObjectSpace());
      
                  }
      
                  catch(AuthenticationException) {
      
                      HttpContext.Current.Response.Status = "401 Unauthorized";
      
                      HttpContext.Current.Response.StatusCode = 401;
      
                      HttpContext.Current.Response.End();
      
                  }
      
              }
      

      As you can see, the main work is performed by the well-known SecurityStrategyComplex and AuthenticatinStandard components, which are used in the client XAF apps. The same built-in SecuritySystemUser and SecuritySystemRole business classes are used as well. The user credentials are retrieved from the request headers and parameters, which are originally specified by the client application initiating the request to the server. Of course, for better safety, this approach must work over HTTPS only. If the specified credentials are wrong, the AuthenticationException error with code "401 Unauthorized" is thrown. If everything is fine, the client’s request is passed further where the CustomAuthenticationDataService instance is created.

      Note that it is necessary for cross-domain operations to modify the server’s response in a speific way. Further details can be found in this KB Article.

      Finally, we will deploy the created service in Azure using the instructions we described in the previous chapter. 

      TAKE SPECIAL NOTE IF YOU UPGRADE THIS PROJECT CODE TO THE LATEST XAF VERSION:
      1. The CanReadMembers method called in the CustomAuthenticationDataService class no longer exists. Refer to the http://www.devexpress.com/issue=Q477749 ticket for a replacement.

      2. The DevExpress.ExpressApp.Security.ClientPermissionRequest class used in the CustomAuthenticationDataService class is now obsolete.  Use 'PermissionRequest' instead. Refer to the https://www.devexpress.com/issue=T322857 ticket for a replacement.

      3. The CreateSelectDataSecurity method called in the CustomAuthenticationServiceHelper class is no longer public. Instead, modify the line as follows: ((ISelectDataSecurityProvider)SecuritySystem.Instance).CreateSelectDataSecurity()


      6. The DXTREME Mobile Client

      This client application will use the CustomAuthenticationDataService we just created to get data and to get information about how to build a UI based on user rights.

      To quickly get started with a DXTREME client, let’s use the recently introduced wizard, which will build CRUD views based on the specified data service. Since our service requires a user name and password, we will have to temporarily disable this feature, so as to not confuse the wizard. This can be done by returning “Sam”, along with an empty string from the GetUserName and GetPassword methods of our Global class respectively.

      ·        Once the wizard completes its work, several views will be created. Let’s rename them as follows:

      ·        - contact-ListView
      - contact-DetailView
      - contact-EditView

      In addition, we will create a logon form, from which the IsUserAllowed service call will be initiated. A user is allowed to enter the application only if the service returns True. In case of a server error (e.g., 401(Unauthorized)) a user is rejected.

       

       

      logon-screen

       

      Once a user is authorized, the contact “ListView” is opened by default. This view has a command to create new contacts, which are available to Admin user only, by default.

      From a list form, a user can go to the contact ”DetailView”, which calls the IsGranted and CanReadMembers service methods. These calls are required for determining the visibility of the Edit and Delete buttons. If a user has no right to edit an object, a special UI Level Security button is displayed (just for the demo). The purpose of this button is to control whether or not the UI should be affected according to the results of our OData authentication service. For instance, if you set the option to Off, the IsGranted call will be ignored and the Edit/Delete buttons will always be displayed.  

       

      detail-screen_google

       

      Pressing the Edit button will take you to the contact “EditView”. Once there, you can modify data and press the Save button when you are done. The save operation will complete only if the user has the right to do so. Otherwise, an error will appear.

       

      screenshot

      Finally, you can DOWNLOAD a working version of this project here (DXperience Universal 12.2.4 is required). 

      A Quick Summary!

      1. We created a custom WCF middle-tier security service, in which we leveraged ready-to-use XAF security system means, such as SecuredDataServer, etc. We didn’t invent anything new, except for hosting the service in a regular ASP.NET application deployed in Azure, because our users inquired about how to do this in the past. Please note that our service is connected to the SQL Azure database, which is powered by our XPO datalayer.

      2. We created an XAF desktop app that is connected to the security service by simply changing the connection string to a service URL. No additional configuration was required, because it is already provided by the XAF security module out-of-the-box. With the XAF client, you can easily perform all the administrative work, such as creating users and roles, configuring security permissions, etc.

      3. We built a custom authentication OData service to provide a bridge from the built-in XAF security system to non-XAF apps. This OData service not only takes data from a middle-tier security service according to the rights of the user talking to it, but also indicates what this user is allowed to do with a certain business object, its fields, etc., allowing for the performance of UI transformations accordingly.

      4. We demonstrated the use of the OData authentication services with a DXTREME mobile client, mainly because more and more XAF customers are interested in creating mobile solutions for their clients. Take special note that could create a Console, WPF or any other application type that “understands” OData. This opens even more opportunities and flexibility for you.


      Disclaimer

      Please take special note that this is just a demonstration post that shows how to use XAF SecurityStrategyComplex class to filter out sensitive data when developing a DevExtreme mobile application.  This is not a complete guideline or recommendation on how to develop your apps by any means, but rather an illustration of our vision at the publication date on how this task can be solved. So, please treat it appropriately, because the described solution may contain bugs or there may be better approaches over time. As of the publication date, we do not ship ready and recommended solutions for developing mobile apps with XAF and the Middle Tier Security feature is at the Beta stage. We are working to finish it and will surely provide additional information regarding this scenario when we get results (we cannot provide any ETA on this for now). That said, we will not be able to update the described solution and samples according to the XAF and DevExtreme updates and also provide immediate solutions or support if something stops working in the future. If you are interested in using the new XAF security system with non-XAF applications, you will probably be interested in adding this ticket to your Support Center Favorites list or subscribe to our team blog, as we may provide additional details there. 

       

       

      Our questions to you…

      Q1. Would you be interested in having a prebuilt project template for the OData authentication service we created?

      Q2. Would you use DXTREME to build a mobile client in addition to your existing XAF desktop app (this is a continuation of an earlier discussion; nevertheless, I wanted to get specific input on this from other users)? Or you would be all right with an XAF ASP.NET application optimized for mobile/tablet use via specialized templates with large buttons, an adaptive menu and other elements providing a superior experience on touch devices (see here for more details)?

      Please post your answers to these questions and your thoughts about this in-depth how-to-series in your comments. Happy XAFing!Smile

      37 comment(s)
      James Zhong
      James Zhong

      Thanks Dennis for your first XAF + Mobile article!

      Basically, I agree with Marco Kummer (see Q447408). It's better for XAF developers to 'hide' separate DXTREME application development. It seems to be a good idea to introduce Web_SmartPhone and Web_Tablet projects into XAF templates, which render the pages differently than the classic Web project.

      12 December, 2012
      James Zhong
      James Zhong

      Suggestion: 'Technical Blogs' should be linked to your website's homepage, just like the old DXv1 days. Otherwise, your potentials and customers won't have to re-visit DX website unless they explicitly need your support service.

      12 December, 2012
      Otgontugs Miimaa 2
      Otgontugs Miimaa 2

      Interesting article. Thanks for sharing. I've been always in doubt to dive into DXTREME, because of failing of former Facebook mobile edition. It was not written in native code, as you might know the tech as DXTREME (HTML5+JS). Fail reason was performance issue. Please correct me if i misunderstood something. But i agree that single code for all mobile devices is fascinating. Is there any comparision (pros, cons article or any research) between native and Html5+JS techs as well as performance? What are pros and cons of native vs DXTREME?

      12 December, 2012
      James S K Makumbi
      James S K Makumbi

      Great article. Thanks for sharing!

      13 December, 2012
      James S K Makumbi
      James S K Makumbi

      Q1 Yes

      Q2 Yes I do intend to use DXTREME to build mobile clients in addition to Desktop and ASP apps. I am worried that an ASP app will not scale well across ALL devices and yet DXTREME allows device targeted development and an early cheap and fast look at the end results.

      13 December, 2012
      Michael Folinsbee
      Michael Folinsbee

      We are interested in exploring XAF cloud deployment. Prospective clients have also asked us about high-level reporting via the iPad. Your blog connects both of these aspects – thanks!

      Q1 – Yes. We support your initiatives that streamline the process of leveraging our investment in XAF and XPO for new platforms.

      Q2 – Based on the demos and discussions so far, I generally agree with Marco’s comments in your recent exchange with him. I would prefer to minimize use of JavaScript and to continue to enhance our existing codebase. It is certainly desirable to offer as seamless support as possible for the current crop of mobile computing variants – Windows RT, Android and iOS – but I am not convinced that any of these platforms readily meet the requirements for our current generation of business applications. We would love to take advantage of DXTREME technology from within XAF by simply adding new modules and views adapted for mobile devices.

      13 December, 2012
      Mohsen Benkhellat
      Mohsen Benkhellat

      Thanks Dennis for your efforts.

      When time permits, I will dig in the sample and see where I can go from there.

      I will be exploring the way to expose Get methods to be used in DXTreme frontend to access XAF model of view (to not be confused with the ViewModel of knockout :-))

      By using WinJS controls from within DXTreme when on Windows 8 and fall back to HTML5 otherwise would be a good way to unify code base IMO.

      13 December, 2012
      Chris Pitt
      Chris Pitt

      Well done Dennis. To answer your questions. we have developed a web app exclusively with XAF and was looking for a way to use the security etc built into XAF on the mobile devices. The timing of this is perfect!

      We plan to do more development in the mobile arena with DXtreme in the future.

      Thank you!

      17 December, 2012
      Evgeniy Meyke
      Evgeniy Meyke

      Q1: YES

      Q2: YES

      17 December, 2012
      Willem de Vries
      Willem de Vries

      Q1: Yes

      Q2: Depends on the level of complexity of either solution path. Both questions: yes

      18 December, 2012
      Paolo Liverani
      Paolo Liverani

      Q1: YES

      Q2: YES

      18 December, 2012
      Franco Bonacchi
      Franco Bonacchi

      Q1: YES

      Q2: YES

      18 December, 2012
      Martin Brekhof
      Martin Brekhof

      Q1: YES

      Q2: I would prefer enhancement of the existing ASP.NET web app (MVC for example) as Tablet and Web-site use are, in my experience, two different kinds of usage (the website being a replacement for the desktop)

      20 December, 2012
      Carlitos
      Carlitos

      Q1: YES!!!

      Q2: YES!!!

      20 December, 2012
      Geoff Davis
      Geoff Davis

      Cracking Article Dennis.

      My client is wanting to move to the cloud with his 6 year old WinForm backend and ASP.NET 2.0 ecommerce frontend application so this has come at the right time.

      I'm still deciding on whether or not to use XAF for the backend and DXTreme Web and Mobile for the frontend or just have one huge ASP.NET MVC for both the backend and frontend or have XAF for the backend and ASP.NET MVC for the frontend, gosh why so many options :-)

      21 December, 2012
      Dennis (DevExpress)
      Dennis (DevExpress)

      Thank you for your feedback, Guys. It is much appreciated.

      @Geoff: Yeah, I hear you...Deciding on the tools for a new project has never been so complicated as it is nowadays. Fortunately, DXperience will support you regardless of the route you choose. Feel free to contact us if we can help you in any way.

      21 December, 2012
      John Pelitidis
      John Pelitidis

      Hi Dennis,

      I have been building a XAF application for the past 15 months. I now accept that I will have to make some parts of my application accessible from iPad and Android, but mostly from the desktop.

      This is a daunting task for me, so can you please consider creating a template in visual studio which sets up a cross platform XAF application with all the security configuration that allows for custom user and roles as well as middle tier security, so that the mobile parts of the application can be built up.

      A fully documented tutorial  should be included, like the Main demo tutorial, that demonstrate the addition of mobile components to the program.

      I guess, I am asking for a new XAF Main demo example that operates on desktop, iPad and mobile phones, with fully documented tutorial.

      26 December, 2012
      Rudy Scott
      Rudy Scott

      Hey Dennis,

      1) YES

      2) MAYBE -- I also like the idea of consuming via MonoTouch and Mono for Android and staying out of JS/HTML altogether.  But if I were to use DXTREME this is probably the way I'd do it.

      Very interesting article.  I'm in a similar position to Geoff.  I notice the 2012 Roadmap talked about decoupling XAF from XPO.  Is that completed now?  Does the OData data source have to be created with XPO or can a XAF application consume OData from another source?

      Also, this seems to emphasize the OData layer as a security device--but could business logic exist in this layer as well?

      24 January, 2013
      Dennis (DevExpress)
      Dennis (DevExpress)

      @Rudy: Thank you for your feedback. I answered your questions at www.devexpress.com/issue=Q459727

      5 February, 2013
      Daniel Großer
      Daniel Großer

      This does not actually work when the XAF application uses domain components, does it? What are the chances of this scenario being supported any time soon?

      13 February, 2013
      Paul Samaniego
      Paul Samaniego

      Hi Dennis,

      This example is very important, I downloaded the file XAF_DXTREME_integration_demo.zip and does not work in version 12.2.7, I get the following error:

      DevExpress.ExpressApp.Security.IRequestSecurity not contain a definition of 'CanReadMembers' Line 64 column 99 in file CustomAuthenticationDataService.svc.

      I would like you to develop a simpler illustration without Windows Azure and ASP.NET access and a video if possible.

      Thank you very much

      22 March, 2013
      Dennis (DevExpress)
      Dennis (DevExpress)

      @Paul: You can find a solution at www.devexpress.com/.../ViewIssue.aspx

      2 April, 2013
      Dennis (DevExpress)
      Dennis (DevExpress)

      @Daniel: I saw in www.devexpress.com/.../ViewIssue.aspx that a customer got it partially working for DC. However, this particular scenario is not officially supported and tested by us. See also:

      www.devexpress.com/.../ViewIssue.aspx

      2 April, 2013
      Dennis (DevExpress)
      Dennis (DevExpress)
      If you are interested in getting DC and OData working together, you may want to track the http://www.devexpress.com/issue=Q482084 ticket.
      2 April, 2013
      John01
      John01

      Q1. Definitely. lf possible also with the option to omit middle-tire when needed.

      Q2. Both. XAF will have to keep up to remain relevant in an increasingly mobile world..

      10 April, 2013
      John01
      John01

      "It seems to be a good idea to introduce Web_SmartPhone and Web_Tablet projects into XAF templates, which render the pages differently than the classic Web project."

      DITTO.

      10 April, 2013
      Andrew Bingham 2
      Andrew Bingham 2

      1 and 2 - Absolutely. For sure. ASAP. Yesterday would be good.

      The whole point for me is to have an XAF app which can auto-generate, (or at least act as the Business and Data tiers for) user interfaces on any platform -  desktop, web, mobile, and whatever is coming next (clothing?).

      25 April, 2013
      Vipul Thakkar 1
      Vipul Thakkar 1

      Hello

      At last here mentioned that this approach is useful for WPF/ Silverlight . "ake special note that could create a Console, WPF or any other application type that “understands” OData. "

      SO I am trying it But not getting how to do it for WPF/ Silverlight.. can you please tell  me how to do it? How it is going to work in Wpf / Silverlight?

      28 May, 2013
      Dennis (DevExpress)
      Dennis (DevExpress)

      @Vipul: You may find the help.devexpress.com  article helpful.

      20 December, 2013
      Lothar Behrens - Lollisoft
      Lothar Behrens - Lollisoft

      Hi,

      Q1: YES!!!

      Q2: YES!!!

      I have tried the sample and was even able to run it without Azure (I do not have an account yet)! Simply changing the connection string for the databases and stuff that points into the Azure Cloud.

      Small issues are with the current release of DevExtreme - probably - that are as of the following:

      app.js: db._url is not defined - why?

         try {

             DXTremeClient.DataManipulationRight = DataManipulationRight("localhost/CustomAuthenticationDataService.svc");//DXTremeClient.db._url);

         } catch (e) {

             // Another dialog is shown

         }

      db.js: browser is not defined - try catch helps

         // Enable partial CORS support for IE < 10

         try {

         if($.browser.msie)

             $.support.cors = true;

         } catch (e) {

             // Another dialog is shown

         }

      Great example - thanks,

      Lothar

      5 January, 2014
      Lothar Behrens - Lollisoft
      Lothar Behrens - Lollisoft

      Hi,

      my last post the line

      DXTremeClient.DataManipulationRight = DataManipulationRight("localhost/CustomAuthenticationDataService.svc");

      was not really required. I do not know why I had that error. The original code is correct.

      But I found three other issues:

      First, the edit button did not apprear as expected. The following code corrects that

      <div data-options="dxView : { name: 'ContactDetails', title: 'Contact' } " >

         <div data-bind="dxCommand: { action: '#ContactEdit/{id}', id: 'edit', title: 'Edit', icon: 'edit', visible: CanEdit }"></div>

         <div data-options="dxContent : { targetPlaceholder: 'myheader' } " >

             <div data-bind="dxToolbar: { items: [

                         { align: 'center', text: 'Contact' },

                         { align: 'right', widget: 'button', options: { text: 'Edit', clickAction: 'handleEditClick' } },

                         { align: 'left', widget: 'button', options: { text: 'Back', clickAction: '#_back' } }

                     ] }">

             </div>

         </div>

      Important is the setup of the visible flag at least in this way:

      visible: CanEdit

      Then the Edit view did not contain a save button. This fixed it:

      <div data-options="dxView : { name: 'ContactEdit', title: 'Contact' } ">

         <div data-bind="dxCommand: { action: handleSave, id: 'save', title: 'Save', icon: 'save' }"></div>

      Last issue was in the security service. The setup of the permissions did work as expected, but not the security query.

      I created a static dictionary where I put the security definitions:

             static Dictionary<string, EntitySetRights> permissions = new Dictionary<string, EntitySetRights>

             {

                 { "Contact", EntitySetRights.All }

             };

      Used this in the initialization:

      public static void InitializeService(DataServiceConfiguration config) {

                 //config.SetEntitySetAccessRule("*", EntitySetRights.All);

                 foreach (var permission in permissions)

                 {

                     config.SetEntitySetAccessRule(permission.Key, permission.Value);

                 }

                 config.SetServiceOperationAccessRule("IsGranted", ServiceOperationRights.AllRead);

                 config.SetServiceOperationAccessRule("IsUserAllowed", ServiceOperationRights.AllRead);

                 config.SetServiceOperationAccessRule("CanReadMembers", ServiceOperationRights.AllRead);

                 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;

                 config.DataServiceBehavior.AcceptProjectionRequests = true;

             }

      And also I used it in IsGranted:

      [WebGet]

             public bool IsGranted(string objectType, string memberName, string objectHandle, string operation) {

                 Type type = XafTypesInfo.Instance.FindTypeInfo(objectType).Type;

                 bool value = ((IRequestSecurity)SecuritySystem.Instance).IsGranted(new ClientPermissionRequest(type, memberName, objectHandle, operation));

                 string key = objectType.Replace("BusinessObjectsLibrary.", "");

                 if (permissions.ContainsKey(key) && permissions[key] == EntitySetRights.AllRead && operation == "Write") return false;

                 if (permissions.ContainsKey(key) && permissions[key] == EntitySetRights.AllRead && operation == "Delete") return false;

                 return value;

             }

      The code is not well tested for other combinations in the security setup. I think, there are some issues when I set EntitySetRights.None for sample.

      So be aware, this is only a little fix.

      Lothar

      13 January, 2014
      Randy Jean
      Randy Jean

      A little late but...

      Q1: Yes

      Q2: Depends on the level of complexity of either solution path. Both questions: yes

      3 March, 2015
      DevUser Query
      DevUser Query

      how  can i used multiple entities in your existing Odata service .

      just suppose you have used single entities like-

      config.SetEntitySetAccessRule("Contact", EntitySetRights.AllRead);

      i want there used another entities set like-

      config.SetEntitySetAccessRule("Person", EntitySetRights.AllRead);

      is that possible if yes how can i declare.

      14 April, 2015
      Dennis (DevExpress)
      Dennis (DevExpress)

      @DevUser Query: Sure, that is possible.  You should just declare a Person class near the existing Contact one and then use the SetEntitySetAccessRule method. Should you have any other questions on this, contact us via the online Support Center at www.devexpress.com/sc

      15 April, 2015
      Kesu lal
      Kesu lal

      Can be change login Url At Runtime

      5 June, 2015
      ALaboTech company
      ALaboTech company

      Hi! At now mobile client contains (localhost/DataService.svc) a service with standart auth method.

      Is it easier to use it and make the whole project of the mobile application apload and use the built-in service? In this case, third-party clients will also be able to authenticate by forming the correct query format to mobile built-in service... Rectify please if I'm wrong...

      17 January, 2018
      Dennis (DevExpress)
      Dennis (DevExpress)

      @Kilo 11: Yes, it may be easier, because this is a built-in feature that also supports the Basic Authentication protocol. Check out the www.devexpress.com/.../faq-new-xaf-html5-javascript-mobile-ui-beta article for more details.

      29 January, 2018

      Please login or register to post comments.