Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.nuget
CustomMembershipProvider
packages
CustomMembershipProvider.sln
README.md

README.md

Custom membership provider integration in Sitefinity

Authentication is an integral part of every web application. In many scenarios, Sitefinity's built-in membership provider (SitefinityMembershipProvider) is sufficient for providing the required authentication functionality. However, you may want to integrate your own custom membership provider, so that you reuse your current database records with other web applications. Or, you may want to migrate from standard ASP applications to Sitefinity and wish to reuse your current authentication store.

Registering such custom membership providers in the web.config file (as in the standard ASP applications) works OK in a small numbe of cases, but will cause an overhead in most cases and scenarios (~ 10 000 or above). The reason is that the MembershipProvider class provides only a single method for filtering users - the GetAllUsers(int pageIndex, int pageSize, out int totalRecords) method, which, as its signature states, uses only paginated data with no support for filtering, seaching, or sorting. This functionality is not sufficient and does not serve well Sitefinity's user interface, which supports filtering, sorting, searching, and paging of user records. Thus, you benefit from:

  • Loading a small amount of users in memory
  • Faster user management

So, how do you fetch filtered, ordered, and paged data from your custom membership provider? With Sitefinity version 8.0, you can configure custom membership providers to support such funcionality by using the IBasicQueryExecutor interface.

IBasicQueryExecutor

This interface exposes a single method - Execute(QueryArgs args). When decorated on a custom memberip provider, this method is called whenever data needs to be retireved from the custom membership provider with the arguments for filtering, paging, sorting, and search, provided in the args variable.

Custom MembershipProvider example

The example in this repository is a fully functional implementation of the standard SqlMembershipProvider with support for filtering, paging, search, and sorting. The example demonstrates you can integrate your custom membership provider to support the user interface of Sitefinity.

Prerequisities

  • A custom membership provider
  • Sitefinity 8.0 or above

API Overview

###QueryArgs The QueryArgs type has several properties which hold the accumulated data from the Linq query expression. The following tables provides more details on the specifics of each property of the QueryArgs object, as well as on the supported queries.

Property Description Query example(s)
PagingArgs

This property has two sub-properties – Skip and Take. When executed against an IQueryable object, the properties hold the values passed to the Skip and Take methods.
NOTE: Call the Skip and Take methods just once in a single query. Otherwise a NotSupportedException is thrown and the order in which the,methods are supplied is not taken into account.

...GetUsers().Where(..).Skip(skipVal).Take(takeVal).ToList()
The query sets the Skip and Take property of the PagingArgs to skipVal and takeVal correspondingly. If Skip or Take are not called, these values will be set to null.
OrderArgs This property is responsible for holding the OrderBy clause, supplied to the method. It has two properties:
  • MemberName - the member by which to order
  • Direction - descending or ascending order
...GetUsers().Where(..).Skip(skipVal).Take(takeVal).OrderBy(x => x.Username).ToList()
The query sets the MemberName to "Username" and Direction to "Ascending". If the query were to hold OrderByDescending instead of OrderBy, the direction would be set to "Descending". Once again the order does not matter and only one OrderBy query can be executed.
Filters This property holds the filters specified in the Where clause. You can have as many Where clauses as you want. The filters are populated in the Filters collection. Each filter consists of:
  • Member object holding the MemberName and Action
  • Action - holding the operator
  • Value - holding the compared value
The support for the Where clause is limited to two examples only:
  • ..GetUsers().Where(x => x.Username == "test")
  • ..GetUsers().Where(x => x.Username == "test" && x.Email == "test@test.com" && ...)
NOTE: Only the && clause us supported. Any other clause triggers a NotSupportedException.

Multiple Where clauses:

..GetUsers().Where(x => x.Username == "test").Where(x => x.Email == "test@test.com")
In the example above, the Member is mapped to "Username", Action to "Equals", and Value to "test".

LastAction This property represents the method executed most recently on the query. In addition to the methods described in the row above, the Any and Count methods are also supported. Any filters specified as predicates in the Count method are added to the filters collection. The same logic is applied for the method Any(). In case the query does not end with the Any or Count methods, the LastAction property is populated with the value "List".

GetUsers().Where(x => x.Username.StartsWith(“test”)).Count()

In the example above, LastAction is populated with "Count" because the query ends with the Count() method.

GetUsers().Where(x => x.Username.StartsWith("test")).Count(x => x.Email.Contains("test@test"))

In the example above, the result is an additional filter with a Member.Name property with value "Email", Action is mapped to "Contains", and Value to "test@test".

QueryType This property represents the return type of the query.

GetUsers().Where(x => x.Username.StartsWith("test")).Count()
sets the query type to IQueryable

GetUsers().Where(x => x.Username.StartsWith("test")).Count()
sets the query type to int

..GetUsers().First()
sets the query type to User

Supported queries

Query type Description Query example(s)
String Filters To filter by a string value Sitefinity supports the following string operations:
  • Contains
  • StartsWith
  • EndsWith
  • Equals
The Member exposes two sub properties:
  • Name - name of the member which is to be filtered
  • Action - holds the name of the method executed most recently on the property
  • ..GetUsers().Where(x => x.Username.StartsWith(“test”))
  • ..GetUsers().Where(x => x.Username.EndsWith(“test”))
  • ..GetUsers().Where(x => x.Username.Contains(“test”))
In the examples above, the filter is populated with "Username" for Member, "StartsWith", "EndsWith", or "Contains", respectively, for Action, and "test" for Value.

Member property:
..GetUsers().Where(x => x.Username.ToUpper(). Contains (“test”))
In the example above, Action is populated with "ToUpper" to indicate that the user name must be compared with uppercase.

Enumerable Filters Sitefinity also supports the Enumerable Contains filter, which means you can compare the value of a property with a predefined list of variables.

var userIds = new Guid[] { Guid.Parse("5498325D-1F86-4151-848E-77E143A0369C"), Guid.Parse("CFE8F05D-24DB-4756-8209-9EECCE44A1D1") };

..GetUsers().Where(x => userIds. Contains (x.Id))

In the example above, the Member.Name property is populated with "Id", the Action is mapped to "Contains", and Value to the "usersIds" collection.

Using the Username property:

var usernames = new string[] { “admin1”, “admin2” };

..GetUsers().Where(x => usernames.Contain(x.Username))

Additional supported filters The methods First and FirstOrDefault are represented using pagination. The same goes for the Single or SingleOrdefault methods.

Methods First and FirstOrDefault identical examples:

GetUsers().Where(x => x.Username.StartsWith(“test”)).FirstOrDefault();

GetUsers().Where(x => x.Username.StartsWith(“test”)).Take(1).ToList();

Methods Single and SingleOrDefault identical examples:

GetUsers().Where(x => x.Username.StartsWith(“test”)).SingleOrDefault();

GetUsers().Where(x => x.Username.StartsWith(“test”)).Take(2).

In the examples above, the Take parameter is set to 2 because of the way the Single method works. The difference here is that if there is more than one match, the Single method throws an exception.
You can’t perform that action at this time.