---
title: Membership
slug: cms-12/api/groups-membership
docTags: 
createdAt: 2026-08-07T16:45:44.000Z
---

A group is a named aggregation of users and content. Users are associated with a group by adding them as members.

Members are represented by the `Member` class.

Members are managed through a service implementing the interface `IMemberService`. This service provides the ability to persist, retrieve, and remove `Members` that you define.

## Access an IMemberService

When the `Groups` feature is installed on an Optimizely Content Management System (CMS) site with the feature's site integration package; you can get an instance of this service from the inversion of control (IoC) container.

Example:

```csharp
var memberService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IMemberService>();
```

When the feature is installed on a non-Optimizely CMS site, you can get an instance of a service from the default factory class provided within the package.

```csharp
var factory = new EPiServer.Social.Groups.DefaultMemberServiceFactory();
var memberService = factory.Create();
```

## Add a member

To add a member, use the `Add(Member)` method of the `IMemberService`. This method accepts an instance of the `Member` class, and returns a reference to an instance of that class, populated with any additional, system-generated data (for example, a unique ID).

```csharp
IMemberService memberService;
GroupId idOfExistingGroup;
Reference user;

// ...
var member = new Member(user, idOfExistingGroup);
memberService.Add(member);
```

If the identified group cannot be found, a `GroupDoesNotExistException` is thrown.

If the member already exists, a `DuplicateMemberException` is thrown.

The above example invokes the request to add a member synchronously. An example of adding a member asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<Member> AddMemberAsync(IMemberService memberService) {
  GroupId idOfExistingGroup;
  Reference user;

  // ...
  var member = new Member(user, idOfExistingGroup);
  var addMemberTask = memberService.AddAsync(member);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var addedMember = await addMemberTask;
  return addedMember;
}
```

## Validate a member

To validate that a user is a member of a group, use the `IsMember(GroupId,Reference)` method of the `IMemberService`. This method accepts an instance of the `GroupId` class, identifying the target group, and an instance of the `Reference` class, identifying the target user. The method returns a Boolean, indicating whether or not the identified user is a member of the identified group.

```csharp
IMemberService memberService;
GroupId idOfExistingGroup;
Reference user;

// ...
bool isMember = memberService.IsMember(idOfExistingGroup, user);
```

In the above example, the request to validate if a user is a group member is invoked synchronously. An example of validating a user's membership in a group asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<bool> ValidateMemberAsync(IMemberService memberService) {
  GroupId idOfExistingGroup;
  Reference user;

  // ...
  var isMemberTask = memberService.IsMemberAsync(idOfExistingGroup, user);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var isValid = await isMemberTask;
  return isValid;
}
```

## Remove a member

To remove a specific instance of Member, which was previously added through the platform, use the `Remove(MemberId)` class. This method accepts an instance of the `MemberId` class, which identifies the `MemberId` to be removed. The result is the deletion of the `Member` corresponding to that ID.

```csharp
IMemberService memberService;

// ...

// Construct or retrieve an ID for an existing member.
var memberId = MemberId.Create("...");
memberService.Remove(memberId);
```

The above example invokes the request to remove a member synchronously. An example of removing a member asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task RemoveMemberAsync(IMemberService memberService) {
  //...

  // Construct or retrieve an ID for an existing member.
  var memberId = MemberId.Create("...");
  var removeMemberTask = memberService.RemoveAsync(memberId);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  await removeMemberTask;
}
```

## Retrieve a member

You can retrieve a specific instance of a `Member`, which was previously added through the platform by using the `Get(MemberId)` method of `IMemberService`. This method accepts an instance of the `MemberId` class, which identifies the `Member` to retrieve. It returns the instance of the `Member` class corresponding to that identifier.

```csharp
IMemberService memberService;

//...

// Construct a MemberId corresponding to the desired member
var memberId = MemberId.Create("...");
var member = memberService.Get(memberId);
```

If the requested `Member` cannot be found, a `MemberDoesNotExistException` is thrown.

The above example invokes the request to retrieve a member synchronously. An example of retrieving a member asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<Member> GetMemberAsync(IMemberService memberService) {
  //...

  // Construct a MemberId corresponding to the desired member
  var memberId = MemberId.Create("...");
  var getMemberTask = memberService.GetAsync(memberId);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var member = await getMemberTask;
  return member;
}
```

To retrieve a collection of members that were previously added through the platform, use the `Get(Criteria)` method. This method accepts an instance of `Criteria`, which contains the specifications to retrieve desired `Members`.

The `Filter` property of the `Criteria` class accepts an instance of the `MemberFilter` class. This class contains the specifications that let you refine the result set of Members you want to retrieve. The properties of the `MemberFilter` class include:

- `Group` – Assigning a value (`GroupId`) to this property refines a result set to Members of the identified group.
- `MemberIds` – Assigning a value (`IEnumerable`) to this property refines a result set to Members identified in the collection.
- `Role` – Assigning a value (`RoleId`) to this property refines a result set to Members assigned the identified role.
- `User` – Assigning a value (`Reference`) to this property refines a result set to Members associated with the identified user.

The specifications of the `MemberFilter` may be applied in conjunction with one another. Each specification, assigned a value in the filter, further refines the result set (a logical AND).

The example below demonstrates the retrieval of a result page of `Members` assigned to a group.

```csharp
IMemberService memberService;
Group existingGroup;

// ...

var criteria = new Criteria<MemberFilter> {
  Filter = new MemberFilter {
    Group = existingGroup.Id
  }
};
var pageOfMembers = memberService.Get(criteria);
```

In the above examples, the request to retrieve members is invoked synchronously. An example of retrieving members asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<ResultPage<Member>> GetMembersAsync(IMemberService memberService) {
  Group existingGroup;

  // ...
  var criteria = new Criteria<MemberFilter> {
    Filter = new MemberFilter {
      Group = existingGroup.Id
    }
  };
  var getMembersTask = memberService.GetAsync(criteria);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var pageOfMembers = await getMembersTask;
  return pageOfMembers;
}
```

The `MemberSortFields` class exposes a set of fields upon which a result set of members may be ordered. You can apply these fields to construct sorting rules associated with your criteria. These fields include:

- `MemberSortFields.Group`
- `MemberSortFields.Id`
- `MemberSortFields.User`

The example below demonstrates how to apply sorting rules to order your result set by group ID in ascending order.

```csharp
var criteria = new Criteria<MemberFilter> {
  // ...
  OrderBy = new List<SortInfo> {
    new SortInfo(MemberSortFields.Group, true)
  }
};
```

For details on using criteria, including information on paging and sorting, see *Criteria* in [Discover the platform](docId\:NKmGS-fLtRQIYLEWZfb69).

## Extend members with composites

A `Member` is a relationship between a user and a group. You may need to associate additional information with members to describe and shape them further. Continuing an earlier example, where a group represents an athletic team, a member may represent a player on the team. You might want to capture information identifying the player's uniform number or primary position.

Just as you can extend a `Group` with data of your design, a `Member` may also be extended by creating a Composite. For an introduction to Composites, see *Composites* in [Discover the platform](docId\:NKmGS-fLtRQIYLEWZfb69).

This section explains the synchronous and asynchronous APIs of the member service that support extending members with composites.

### Add a composite member

To save a Composite Member that you defined, use the `Add<TExtension>(Member, TExtension)` method of the `IMemberService`. This method accepts an instance of the `Member` class and an instance of `TExtension`. It returns an instance of `Composite<Member,TExtension>`.

Consider the following class, which represents a sample of extension data:

```csharp
public class Player {
  public int UniformNumber {
    get;
    set;
  }
  public string Position {
    get;
    set;
  }
}
```

In the example below, a `Member` is composed with an instance of this extension class:

```csharp
IMemberService memberService;
GroupId existingGroup;
Reference user;

// ...
var member = new Member(user, existingGroup);
var extension = new Player {
  UniformNumber = 2,
    Position = "Shortstop"
};
var compositeMember = memberService.Add(member, extension);
```

The above example invokes the request to add a member synchronously. An example of adding a member asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<Composite<Member, Player>> AddMemberAsync(IMemberService memberService) {
  // ...
  GroupId existingGroup;
  Reference user;

  // ...
  var member = new Member(user, existingGroup);
  var extension = new Player {
    UniformNumber = 2,
      Position = "Shortstop"
  };
  var addMemberTask = memberService.AddAsync(member, extension);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var compositeMember = await addMemberTask;
  return compositeMember;
}
```

### Update a composite member

To update a specific instance of a Composite Member, which was previously added through the platform, use the `Update<TExtension>(MemberId, TExtension)` method of the `IMemberService`. This method accepts an instance of the `MemberId` class and an instance of `TExtension`. It returns an instance of `Composite<Member,TExtension>`.

Consider the following class, which represents a sample of extension data:

```csharp
public class Player {
  public int UniformNumber {
    get;
    set;
  }
  public string Position {
    get;
    set;
  }
}
```

For this example, the below `IMemberService` is properly implemented

```csharp
IMemberService memberService;

// ...

// Construct a MemberId corresponding to the desired member
MemberId existingMemberId;
var newExtension = new Player {
  UniformNumber = 3,
    Position = "Pitcher"
};
memberService.Update(existingMemberId, newExtension);
```

The above example invokes the request to update a member synchronously. An example of updating a member asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<Composite<Member, Player>> UpdateMemberAsync(IMemberService memberService) {
  // ...

  // Construct a MemberId corresponding to the desired member
  MemberId existingMemberId;
  var newExtension = new Player {
    UniformNumber = 3,
      Position = "Pitcher"
  };
  var updateMemberTask = memberService.UpdateAsync(existingMemberId, newExtension);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var updatedMember = await updateMemberTask;
  return updatedMember;
}
```

### Retrieve a composite member

To retrieve a specific instance of a Composite Member, which was previously added through the platform, use the `Get<TExtension>(MemberId)` method. This method accepts an instance of the `MemberId` class, which identifies the `Member` to retrieve. It returns the instance of the `Composite<Member,TExtension>` class corresponding to that identifier.

```csharp
IMemberService memberService;

//...

// Construct a MemberId corresponding to the desired member
var memberId = MemberId.Create("...");
var compositeMember = memberService.Get<MyMemberExtension>(memberId);
```

If a Composite Member with the specified ID and extension type cannot be found, a `MemberDoesNotExistException` is thrown.

The above example invokes the request to retrieve a member synchronously. An example of retrieving a member asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<Composite<Member, MyMemberExtension>> GetMemberAsync(IMemberService memberService) {
  //...

  // Construct a MemberId corresponding to the desired member
  var memberId = MemberId.Create("...");
  var getMemberTask = memberService.GetAsync<MyMemberExtension>(memberId);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var compositeMember = await getMemberTask;
  return compositeMember;
}
```

To retrieve a collection of Composite Members, which were previously added through the platform, use the `Get<TExtension>(CompositeCriteria<MemberFilter,TExtension>)` method. This method accepts an instance of `CompositeCriteria[MemberFilter,TExtension]`, which contains the specifications necessary to retrieve the desired Members.

The `Filter` property of the `CompositeCriteria<MemberFilter,TExtension>` class accepts an instance of the `MemberFilter` class. This class contains the specifications that let you refine the result set of `Members` that you want to retrieve.

The `ExtensionFilter` property of the `CompositeCriteria<MemberFilter,TExtension>` class accepts a `FilterExpression` that lets you specify a Boolean expression to refine the result set further by values represented within your extension data. (For information on this type of filter, see *Composite Criteria* and *Filtering Composites* in [Discover the platform](docId\:NKmGS-fLtRQIYLEWZfb69).

Consider the following class, which represents a sample of extension data:

```csharp
public class Player {
  public int UniformNumber {
    get;
    set;
  }
  public string Position {
    get;
    set;
  }
}
```

In the example below, a page of Members composed with Player is retrieved, where the players have a position of "Shortstop":

```csharp
IMemberService memberService;

// ...

var criteria = new CompositeCriteria<MemberFilter,
  Player> {
    ExtensionFilter = FilterExpressionBuilder<Player> .Field(e => e.Position).EqualTo("Shortstop")
  };
var pageOfMembers = memberService.Get(criteria);
```

In the above example, the request to retrieve members is invoked synchronously. An example of retrieving members asynchronously using the asynchronous overload with C#'s async and await keywords is described below.

```csharp
private async Task<ResultPage<Composite<Member, Player>>> GetMembersAsync(IMemberService memberService) {
  // ...
  var criteria = new CompositeCriteria<MemberFilter,
    Player> {
      ExtensionFilter = FilterExpressionBuilder<Player> .Field(e => e.Position).EqualTo("Shortstop")
    };
  var getMembersTask = memberService.GetAsync(criteria);

  //Do other application specific work in parallel while the task executes.
  //....

  //Wait until the task runs to completion.
  var pageOfMembers = await getMembersTask;
  return pageOfMembers;
}
```

The fields of your extension data may also be applied when sorting your result set. The example below demonstrates the use of an extension data field in defining a sorting rule.

```csharp
var criteria = new CompositeCriteria<MemberFilter,
  Player> {
    // ...

    OrderBy = new List<SortInfo> {
      new SortInfo(new SortField(FilterExpressionBuilder<Player> .Field(e => e.UniformNumber)), true)
    }
  };
```

For details about using criteria, including information on paging and sorting, see *Criteria* in [Discover the platform](docId\:NKmGS-fLtRQIYLEWZfb69).
