This example demonstrates how to access data protected by the Security System from your Non-XAF application using EF Core for data access. The application outputs secured data to the console.
If you are using XPO ORM for data access, follow this tutorial.
-
Download and run our Unified Component Installer or add NuGet feed URL to Visual Studio NuGet feeds.
We recommend that you select all products when you run the DevExpress installer. It will register local NuGet package sources and item / project templates required for these tutorials. You can uninstall unnecessary components later.
NOTE
If you have a pre-release version of our components, for example, provided with the hotfix, you also have a pre-release version of NuGet packages. These packages will not be restored automatically and you need to update them manually as described in the Updating Packages article using the Include prerelease option.
-
Create a new .NET 6 console application or use an existing application.
-
Add DevExpress NuGet packages to your project:
<PackageReference Include="DevExpress.ExpressApp.EFCore" Version="22.2.3" /> <PackageReference Include="DevExpress.Persistent.BaseImpl.EFCore" Version="22.2.3" />
-
Install Entity Framework Core, as described in the Installing Entity Framework Core article.
-
Open the application configuration file (App.config_. Add the following line to this file.
<add name="ConnectionString" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=EFCoreTestDB;Integrated Security=True;MultipleActiveResultSets=True"/>
NOTE
The Security System requires Multiple Active Result Sets in EF Core-based applications connected to the MS SQL database. We do not recommend that you remove
MultipleActiveResultSets=True;
from the connection string or set theMultipleActiveResultSets
parameter tofalse
.
-
Create an instance of
TypesInfo
required for the correct operation of the Security System.TypesInfo typesInfo = new TypesInfo();
-
Initialize the Security System.
AuthenticationStandard authentication = new AuthenticationStandard(); SecurityStrategyComplex security = new SecurityStrategyComplex(typeof(PermissionPolicyUser), typeof(PermissionPolicyRole), authentication, typesInfo);
-
Create a SecuredEFCoreObjectSpaceProvider object. It allows you to create a EFCoreObjectSpace to ensure a secured data access.
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; var objectSpaceProvider = new SecuredEFCoreObjectSpaceProvider<ApplicationDbContext>(security, typesInfo, connectionString, (builder, connectionString) => builder.UseSqlServer(connectionString).UseChangeTrackingProxies());
-
Call CreateDemoData method at the beginning of the Main method of Program.cs:
private static void CreateDemoData(string connectionString, TypesInfo typesInfo) { using (var objectSpaceProvider = new EFCoreObjectSpaceProvider<ApplicationDbContext>(typesInfo, connectionString, (builder, connectionString) => builder.UseSqlServer(connectionString).UseChangeTrackingProxies())) using (var objectSpace = objectSpaceProvider.CreateUpdatingObjectSpace(true)) { new Updater(objectSpace).UpdateDatabase(); } }
For more details about how to create demo data from code, see the Updater.cs class.
-
Perform a logon. The code below demonstrates how to do this as a user named "User" who has an empty password.
string userName = "User"; string password = string.Empty; authentication.SetLogonParameters(new AuthenticationStandardLogonParameters(userName, password)); IObjectSpace loginObjectSpace = objectSpaceProvider.CreateNonsecuredObjectSpace(); security.Logon(loginObjectSpace);
-
Create ObjectSpace instance to access protected data and use its data manipulation APIs (for instance, IObjectSpace.GetObjects) OR if you prefer, the familiar DbContext object accessible through the EFCoreObjectSpace.DbContext property.
StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("List of the 'Employee' objects:\n"); using(IObjectSpace securedObjectSpace = objectSpaceProvider.CreateObjectSpace()) { // The EFCore way: // var dbContext = ((EFCoreObjectSpace)securedObjectSpace).DbContext; // // The XAF way: foreach(Employee employee in securedObjectSpace.GetObjects<Employee>()) { stringBuilder.Append(string.Format("Full name: {0}\n", employee.FullName)); if(security.CanRead(employee, nameof(Department))) { stringBuilder.Append(string.Format("Department: {0}\n", employee.Department.Title)); } else { stringBuilder.Append("Department: *******\n"); } } }
Note that ObjectSpace returns default values (for instance, null) for protected object properties - it is secure even without any custom UI. Use the SecurityStrategy.CanRead method to determine when to mask default values with the "*******" placeholder in the UI.
Our console application will display employees and mask departments if their titles do not contain 'Development'.