This example demonstrates how to access data protected by the Security System from a non-XAF Web Forms application. You will also learn how to execute Create, Write and Delete data operations taking into account security permissions.
For simplicity, the instructions include only C# code snippets. For the complete C# and VB code, see the CS and VB sub-directories.
-
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.
- Implement XpoDataStoreProviderService to create Data Store Provider and access its value in singleton manner.
public static class XpoDataStoreProviderService {
private static IXpoDataStoreProvider dataStoreProvider;
public static IXpoDataStoreProvider GetDataStoreProvider(IDbConnection connection, bool enablePoolingInConnectionString) {
if(dataStoreProvider == null) {
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
dataStoreProvider = XPObjectSpaceProvider.GetDataStoreProvider(connectionString, connection, enablePoolingInConnectionString);
}
return dataStoreProvider;
}
}
In the Web.config file, add the connection string.
<add name="ConnectionString" connectionString="Data Source=DBSERVER;Initial Catalog=XafSolution;Integrated Security=True"/>
- Implement the ConnectionHelper class.
Implement the GetObjectSpaceProvider
method to create a new SecuredObjectSpaceProvider
instance.
public static SecuredObjectSpaceProvider GetObjectSpaceProvider(SecurityStrategyComplex security) {
SecuredObjectSpaceProvider objectSpaceProvider = new SecuredObjectSpaceProvider(security, XpoDataStoreProviderService.GetDataStoreProvider(null, true), true);
RegisterEntities(objectSpaceProvider);
return objectSpaceProvider;
}
The RegisterEntities
method needs to initialize the Types Info
system and register the business objects, which you will access from your code.
private static void RegisterEntities(SecuredObjectSpaceProvider objectSpaceProvider) {
objectSpaceProvider.TypesInfo.RegisterEntity(typeof(Employee));
objectSpaceProvider.TypesInfo.RegisterEntity(typeof(PermissionPolicyUser));
objectSpaceProvider.TypesInfo.RegisterEntity(typeof(PermissionPolicyRole));
}
Call CreateDemoData
method at the end of the Application_Start
method of Global.asax.cs:
```csharp
private static void CreateDemoData(string connectionString) {
using(var objectSpaceProvider = new XPObjectSpaceProvider(connectionString)) {
ConnectionHelper.RegisterEntities(objectSpaceProvider);
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](/XPO/DatabaseUpdater/Updater.cs) class.
Implement the GetSecurity
method to create and initialize the Security System.
public static SecurityStrategyComplex GetSecurity(string authenticationName, object parameter) {
AuthenticationMixed authentication = new AuthenticationMixed();
authentication.LogonParametersType = typeof(AuthenticationStandardLogonParameters);
authentication.AddAuthenticationStandardProvider(typeof(PermissionPolicyUser));
authentication.AddIdentityAuthenticationProvider(typeof(PermissionPolicyUser));
authentication.SetupAuthenticationProvider(authenticationName, parameter);
SecurityStrategyComplex security = new SecurityStrategyComplex(typeof(PermissionPolicyUser), typeof(PermissionPolicyRole), authentication);
security.RegisterXPOAdapterProviders();
return security;
}
Create the Login.aspx page, add ASPxTextBox to enter the login/password. Then, add 'Log In' ASPxButton to log in.
protected void LoginButton_Click(object sender, EventArgs e) {
string userName = UserNameBox.Text;
string password = PasswordBox.Text;
AuthenticationStandardLogonParameters parameters = new AuthenticationStandardLogonParameters(userName, password);
SecurityStrategyComplex security = ConnectionHelper.GetSecurity(typeof(AuthenticationStandardProvider).Name, parameters);
SecuredObjectSpaceProvider objectSpaceProvider = ConnectionHelper.GetObjectSpaceProvider(security);
IObjectSpace logonObjectSpace = objectSpaceProvider.CreateObjectSpace();
try {
security.Logon(logonObjectSpace);
}
catch { }
if(security.IsAuthenticated) {
SetCookie(userName);
FormsAuthentication.RedirectFromLoginPage(userName, true);
}
else {
ClientScript.RegisterStartupScript(GetType(), null, "errorMessage();", true);
}
security.Dispose();
objectSpaceProvider.Dispose();
}
The LoginButton_Click
method initializes the Security System and tries to log in the user by the specified user name and password.
If the user was successfully logged in, the Security System creates a cookie with the specified user name.
If the Security System can not find the user by specified credentials, it throws an exception. In this example, we handle this exception and display an error message with the client script.
function errorMessage() {
alert("User name or password is incorrect");
}
Create the Default.aspx page and add Log Off ASPxButton to log out and return to the login page.
protected void LogoutButton_Click(object sender, EventArgs e) {
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
Add ASPxGridView to display data in the grid format.
-
Initialize the Security System in the
Page_Init
event handler. Now you can createSecuredObjectSpace
and use its data manipulation APIs (for instance, IObjectSpace.GetObjects) OR if you prefer, the familiarUnitOfWork
object accessible through the SecuredObjectSpace.Session property.protected void Page_Init(object sender, EventArgs e) { security = ConnectionHelper.GetSecurity(typeof(IdentityAuthenticationProvider).Name, HttpContext.Current.User.Identity); objectSpaceProvider = ConnectionHelper.GetObjectSpaceProvider(security); IObjectSpace logonObjectSpace = objectSpaceProvider.CreateObjectSpace(); security.Logon(logonObjectSpace); objectSpace = objectSpaceProvider.CreateObjectSpace(); // The XAF way: // var employees = securedObjectSpace.GetObjects<Employee>(); // // The XPO way: EmployeeDataSource.Session = ((XPObjectSpace)objectSpace).Session; DepartmentDataSource.Session = ((XPObjectSpace)objectSpace).Session; // ... }
Also, you need to assign the
Session
to ASPxGridView Data Sources. -
Check the read operation for appropriate members before each ASPxGridView cell is displayed
The Data Source contains only the data that is filtered based on security permissions, but we still have to handle protected data in UI. In the ASPxGridView.HtmlDataCellPrepared event handler, display the '*******' placeholder instead of a default value returned by secured Data Source.
protected void EmployeeGrid_HtmlDataCellPrepared(object sender, ASPxGridViewTableDataCellEventArgs e) { Employee employee = objectSpace.GetObjectByKey<Employee>(e.KeyValue); string memberName = GetMemberName(e.DataColumn); if(!security.CanRead(employee, memberName)) { e.Cell.Text = "*******"; } } private string GetMemberName(GridViewDataColumn column) { return column?.FieldName.Split('!')[0]; }
-
Check Create and Delete operations to create/ not create buttons and delete them
Hide appropriate buttons in the ASPxGridView.CommandButtonInitialize event handler.
protected void EmployeeGrid_CommandButtonInitialize(object sender, ASPxGridViewCommandButtonEventArgs e) { if(e.ButtonType == ColumnCommandButtonType.New) { if(!security.CanCreate<Employee>()) { e.Text = string.Empty; } } if(e.ButtonType == ColumnCommandButtonType.Delete) { Employee employee = ((ASPxGridView)sender).GetRow(e.VisibleIndex) as Employee; e.Visible = security.CanDelete(employee); } }
-
Check Read and Write operations for editors in Popup Edit Form
Handle the ASPxGridView.CellEditorInitialize event to display the '*******' placeholder and disable editors based on security permissions.
protected void EmployeeGrid_CellEditorInitialize(object sender, ASPxGridViewEditorEventArgs e) { Employee employee = objectSpace.GetObjectByKey<Employee>(e.KeyValue); string memberName = GetMemberName(e.Column); if(!security.CanRead(employee, memberName)) { e.Editor.Value = "*******"; e.Editor.Enabled = false; } else if(!security.CanWrite(employee, memberName)) { e.Editor.Enabled = false; } }
-
Commit changes to database on inserting, updating, or deleting a row
Handle ASPxGridView.RowInserted, ASPxGridView.RowUpdated, and ASPxGridView.RowDeleted events.
protected void EmployeeGrid_RowUpdated(object sender, DevExpress.Web.Data.ASPxDataUpdatedEventArgs e) { objectSpace.CommitChanges(); } protected void EmployeeGrid_RowDeleted(object sender, DevExpress.Web.Data.ASPxDataDeletedEventArgs e) { objectSpace.CommitChanges(); } protected void EmployeeGrid_RowInserted(object sender, DevExpress.Web.Data.ASPxDataInsertedEventArgs e) { objectSpace.CommitChanges(); }
-
Dispose of the objects, which were created, when the page is unloaded
protected void Page_Unload(object sender, EventArgs e) { objectSpace.Dispose(); security.Dispose(); objectSpaceProvider.Dispose(); }
-
Log in a 'User' with an empty password.
-
Press the Logout button and log in as 'Admin' to see all the records.