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.
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.
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.
- A custom membership provider
- Sitefinity 8.0 or above
###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. |
...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:
|
...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:
|
The support for the Where clause is limited to two examples only:
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". |
In the example above, LastAction is populated with "Count" because the query ends with the Count() method.
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. |
|
Query type | Description | Query example(s) |
String Filters |
To filter by a string value Sitefinity supports the following string operations:
|
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.
|