Add EF Core Middle Tier Security to an Existing WinForms Application
- 5 minutes to read
This topic contains step-by-step instructions on how to add a Middle Tier Security project with an Entity Framework Core DbContext to a WinForms application.
Use XAF Solution Wizard to Add a Middle Tier Security Project
Use the Solution Wizard to add a Middle Tier Security project to your application. Right-click the solution in the Solution Explorer and choose Add DevExpress Item | New Project….
Select the .NET platform and run the XAF Solution Wizard.
Choose the Middle Tier Security option and specify the project name.
Select the Entity Framework Core ORM for your application.
Choose Standard authentication on the Choose Security page. The wizard generates JWT authentication scaffolding code.
On the next page, skip selecting additional modules and click Finish.
The wizard adds the MySolution.MiddleTier project to the solution.
Configure the Application
If the name of the EF Core DbContext class in the generated Middle Tier Security project differs from the DbContext name in the the main module project (MySolution.Module), change the DbContext class name in the following files:
MySolution.MiddleTier\Startup.cs
MySolution.MiddleTier\MiddleTierSetup.cs
Add the following NuGet package to the MySolution.Win project:
DevExpress.ExpressApp.Security.EFCore.Extensions.Win
.Because the Middle Tier Security uses the XAF Security System, it requires that the
ApplicationUser
andApplicationUserLoginInfo
persistent classes are defined within your application to store user account data. If the MySolution.Module project does not contain these classes, add them manually as described in the following topic: Use the Security System.If the MySolution.Win\Program.cs contains the following autogenerated code lines, delete them:
static class Program {
[STAThread]
public static int Main(string[] args) {
// ...
// Delete the code below.
// if (ContainsArgument(args, "updateDatabase")) {
// using var dbUpdater = new WinDBUpdater(() => winApplication);
// return dbUpdater.Update(
// forceUpdate: ContainsArgument(args, "forceUpdate"),
// silent: ContainsArgument(args, "silent"));
// }
}
}
- If the WinForms application’s Startup.cs file contains the following code used to update the database, remove the code.
public class ApplicationBuilder : IDesignTimeApplicationFactory {
public static WinApplication BuildApplication(string connectionString) {
var builder = WinApplication.CreateBuilder();
// ...
// Remove the code below.
// builder.AddBuildStep(application => {
// application.ConnectionString = connectionString;
#if DEBUG
// if(System.Diagnostics.Debugger.IsAttached && application.CheckCompatibilityType == CheckCompatibilityType.DatabaseSchema) {
// application.DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways;
// }
#endif
// });
}
}
- If the application’s Startup.cs file contains code that adds EF Core ObjectSpace providers, delete the line that configures the database provider’s connection string and replace it with code that configures the connection to the Middle Tier Security server. Additionally, replace the code that registers the secured object space with the version without security:
public static WinApplication BuildApplication(string connectionString) {
var builder = WinApplication.CreateBuilder();
// ...
builder.ObjectSpaceProviders
// Remove the code below.
//.AddSecuredEFCore()
// .WithDbContext<MySolutionEFCoreDbContext>((application, options) => {
// options.UseSqlServer(connectionString);
// options.UseChangeTrackingProxies();
// options.UseObjectSpaceLinkProxies();
//})
// Add the code below.
.AddEFCore()
.WithDbContext<MySolutionEFCoreDbContext>((application, options) => {
options.UseMiddleTier(application.Security);
options.UseChangeTrackingProxies();
options.UseObjectSpaceLinkProxies();
})
}
- If the application’s Startup.cs file contains code that adds Integrated Security or Windows Security, remove this code.
public static WinApplication BuildApplication(string connectionString) {
var builder = WinApplication.CreateBuilder();
// ...
// Remove the code below.
//builder.Security
// .UseIntegratedMode(options => {
// options.RoleType = typeof(PermissionPolicyRole);
// options.UserType = typeof(DXApplication1.Module.BusinessObjects.ApplicationUser);
// options.UserLoginInfoType = typeof(DXApplication1.Module.BusinessObjects.ApplicationUserLoginInfo);
// })
// .UsePasswordAuthentication();
// ...
}
- In the same file, add code that initializes Middle Tier Security.
public static WinApplication BuildApplication(string connectionString) {
var builder = WinApplication.CreateBuilder();
// ...
builder.Security
.UseMiddleTierMode(options => {
// The Middle Tier Server URL in the code below is the default setting for debug mode and may be different in your application.
// You can check this setting in the Middle Tier project's Properties/launchSettings.json file.
options.BaseAddress = new Uri("https://localhost:44319/");
options.Events.OnHttpClientCreated = client => client.DefaultRequestHeaders.Add("Accept", "application/json");
options.Events.OnCustomAuthenticate = (sender, security, args) => {
args.Handled = true;
HttpResponseMessage msg = args.HttpClient.PostAsJsonAsync("api/Authentication/Authenticate", (AuthenticationStandardLogonParameters)args.LogonParameters).GetAwaiter().GetResult();
string token = (string)msg.Content.ReadFromJsonAsync(typeof(string)).GetAwaiter().GetResult();
if(msg.StatusCode == HttpStatusCode.Unauthorized) {
throw new UserFriendlyException(token);
}
msg.EnsureSuccessStatusCode();
args.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
};
})
.UsePasswordAuthentication();
// ...
}
If the WinForms application uses the Audit Trail module, remove the code that registers it from the WinForms application.
In the Startup.cs file, modify the code in the
ApplicationBuilder.BuildApplication
method so that the DbContext is configured without the audit feature:
public static WinApplication BuildApplication(string connectionString) {
//...
builder.ObjectSpaceProviders
.AddEFCore()
// Remove the code below.
//.WithAuditedDbContext(contexts => {
// contexts.Configure<MySolutionEFCoreDbContext, MySolutionAuditingDbContext>(
// (application, businessObjectDbContextOptions) => {
// businessObjectDbContextOptions.UseSqlServer(connectionString);
// businessObjectDbContextOptions.UseChangeTrackingProxies();
// businessObjectDbContextOptions.UseObjectSpaceLinkProxies();
// },
// (application, auditHistoryDbContextOptions) => {
// auditHistoryDbContextOptions.UseSqlServer(connectionString);
// auditHistoryDbContextOptions.UseChangeTrackingProxies();
// auditHistoryDbContextOptions.UseObjectSpaceLinkProxies();
// });
//})
// Add the code below.
.WithDbContext<MySolutionEFCoreDbContext>((application, options) => {
options.UseMiddleTier(application.Security);
options.UseChangeTrackingProxies();
options.UseObjectSpaceLinkProxies();
})
}
Run the Application
Right-click the Solution node in the Solution Explorer and choose Properties. In the Solution Property Pages dialog, expand the Common Properties node and select Startup Project. Choose the Multiple Startup Projects option and select the Start action for the Web API and MySolution.Win projects.
Click the Run button to run the application.