Files
RavenDB.Identity/Sample
2019-03-04 16:58:35 -06:00
..
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00
2019-03-04 16:58:35 -06:00

RavenDB.Identity Sample

This is a Razor Pages sample that shows how to use Raven.Identity.

There are four areas of interest:

  1. appsettings.json - where we configure our connection to Raven.
  2. AppUser.cs - our user class containing any user data like FirstName and LastName.
  3. RavenSaveChangesAsyncFilter.cs - where we save changes to Raven after actions finish executing. This makes sense for a Razor Pages project. For an MVC or Web API project, use a RavenController base class instead.
  4. Startup.cs - where we wire up everything

More details below.

1. appsettings.json - connection to Raven

Our appsettings.json file defines our connection to Raven. This is done using the RavenDB.DependencyInjection package.

"RavenSettings": {
	"Urls": [
		"http://live-test.ravendb.net"
	],
	"DatabaseName": "Raven.Identity.Sample",
	"CertFilePath": "",
	"CertPassword": ""
},

2. AppUser.cs - user class

We create our own AppUser class to hold user data:

public class AppUser : Raven.Identity.IdentityUser
{
    /// <summary>
    /// The full name of the user.
    /// </summary>
    public string FullName { get; set; }
}

While this step isn't strictly necessary -- it's possible to skip AppUser and just use the built-in Raven.Identity.IdentityUser -- we recommend creating an AppUser class so you can extend your users with app-specific data.

3. RavenSaveChangesAsyncFilter

In Startup.cs (next step), we'll tell AspNetCore to create an IAsyncDocumentSession for every request. But we need to .SaveChangesAsync() for anything to persist in Raven.

While we could call .SaveChangesAsync() in the code-behind of every Razor page, that is tedious and error prone. Instead, we create a Razor action filter to save changes, RaveSaveChangesAsyncFilter.cs:

/// <summary>
/// Razor Pages filter that saves any changes after the action completes.
/// </summary>
public class RavenSaveChangesAsyncFilter : IAsyncPageFilter
{
    private readonly IAsyncDocumentSession dbSession;

    public RavenSaveChangesAsyncFilter(IAsyncDocumentSession dbSession)
    {
        this.dbSession = dbSession;
    }

    public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
    {
        await Task.CompletedTask;
    }

    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
    {
        var result = await next.Invoke();

        // If there was no exception, and the action wasn't cancelled, save changes.
        if (result.Exception == null && !result.Canceled)
        {
            await this.dbSession.SaveChangesAsync();
        }
    }
}

For MVC and Web API projects can use an action filter, or may alternately use a RavenController base class to accomplish the same thing.

4. Start.cs, wiring it all together

In Startup.cs, we wire up all of the above steps:

public void ConfigureServices(IServiceCollection services)
{
	// Grab our RavenSettings object from appsettings.json.
    services.Configure<RavenSettings>(Configuration.GetSection("RavenSettings"));

	// Add an IDocumentStore singleton, with settings pulled from the RavenSettings.
    services.AddRavenDbDocStore();

    // Add a scoped IAsyncDocumentSession. For the sync version, use .AddRavenSession() instead.
    // Note: Your code is responsible for calling .SaveChangesAsync() on this. This Sample does so via the RavenSaveChangesAsyncFilter.
    services.AddRavenDbAsyncSession();

	// Use Raven for our users
	var identityModel = services.AddRavenDbIdentity<AppUser>();

	// Optional: some default Razor Pages UI for login/register/forgot password/etc.
	identityBuilder.AddDefaultUI(UIFramework.Bootstrap4); 

	// Call .SaveChangesAsync() after each action.
	services
		.AddMvc(o => o.Filters.Add<RavenSaveChangesAsyncFilter>())
		.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}