Channels
June 16, 2026 ยท View on GitHub
This guide shows how to migrate channel operations from stream-chat-net to getstream-net.
Create or Get a Channel
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
// With channel ID and members
var channel = await channelClient.GetOrCreateAsync("messaging", "general",
"admin-user", "user-1", "user-2");
// With detailed request
var channel = await channelClient.GetOrCreateAsync("messaging", "general",
new ChannelGetRequest
{
Data = new ChannelRequest
{
CreatedBy = new UserRequest { Id = "admin-user" },
Members = new[] { new ChannelMember { UserId = "user-1" } }
}
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
// With channel ID
var response = await chatClient.GetOrCreateChannelAsync("messaging", "general",
new ChannelGetOrCreateRequest
{
Data = new ChannelInput
{
CreatedByID = "admin-user",
Members = new List<ChannelMemberRequest>
{
new ChannelMemberRequest { UserID = "user-1" },
new ChannelMemberRequest { UserID = "user-2" }
}
}
});
Key changes:
GetOrCreateAsync()onIChannelClientbecomesGetOrCreateChannelAsync()onChatClientChannelGetRequestbecomesChannelGetOrCreateRequest;ChannelRequestbecomesChannelInputCreatedBy(aUserRequestobject) becomesCreatedByID(a string)- Members use
ChannelMemberRequestobjects instead ofChannelMember
Create a Distinct (Member-based) Channel
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
var channel = await channelClient.GetOrCreateAsync("messaging",
new ChannelGetRequest
{
Data = new ChannelRequest
{
CreatedBy = new UserRequest { Id = "user-1" },
Members = new[]
{
new ChannelMember { UserId = "user-1" },
new ChannelMember { UserId = "user-2" }
}
}
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
var response = await chatClient.GetOrCreateDistinctChannelAsync("messaging",
new ChannelGetOrCreateRequest
{
Data = new ChannelInput
{
CreatedByID = "user-1",
Members = new List<ChannelMemberRequest>
{
new ChannelMemberRequest { UserID = "user-1" },
new ChannelMemberRequest { UserID = "user-2" }
}
}
});
Key changes:
- No-ID channel creation uses
GetOrCreateDistinctChannelAsync()instead ofGetOrCreateAsync()without an ID
Add and Remove Members
Before (stream-chat-net):
using StreamChat.Clients;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
// Add members
await channelClient.AddMembersAsync("messaging", "general", "user-3", "user-4");
// Remove members
await channelClient.RemoveMembersAsync("messaging", "general",
new[] { "user-3", "user-4" }, msg: null);
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
// Add members
await chatClient.UpdateChannelAsync("messaging", "general", new UpdateChannelRequest
{
AddMembers = new List<ChannelMemberRequest>
{
new ChannelMemberRequest { UserID = "user-3" },
new ChannelMemberRequest { UserID = "user-4" }
}
});
// Remove members
await chatClient.UpdateChannelAsync("messaging", "general", new UpdateChannelRequest
{
RemoveMembers = new List<string> { "user-3", "user-4" }
});
Key changes:
- Dedicated
AddMembersAsync()/RemoveMembersAsync()methods become part ofUpdateChannelAsync()withAddMembers/RemoveMembersproperties - Members to add use
ChannelMemberRequestobjects; members to remove use string user IDs
Query Channels
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
var response = await channelClient.QueryChannelsAsync(new QueryChannelsOptions
{
Filter = new Dictionary<string, object>
{
{ "type", "messaging" },
{ "members", new Dictionary<string, object> { { "$in", new[] { "user-1" } } } }
},
Sort = new[] { new SortParameter { Field = "last_message_at", Direction = SortDirection.Descending } },
Limit = 10
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
var response = await chatClient.QueryChannelsAsync(new QueryChannelsRequest
{
FilterConditions = new Dictionary<string, object>
{
{ "type", "messaging" },
{ "members", new Dictionary<string, object> { { "$in", new[] { "user-1" } } } }
},
Sort = new List<SortParamRequest>
{
new SortParamRequest { Field = "last_message_at", Direction = -1 }
},
Limit = 10
});
Key changes:
QueryChannelsAsync()moves fromIChannelClienttoChatClientFilterbecomesFilterConditions- Sort uses
SortParamRequestwithDirection = -1(descending) or1(ascending) instead ofSortDirectionenum
Update a Channel
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
await channelClient.UpdateAsync("messaging", "general", new ChannelUpdateRequest
{
Data = new ChannelRequest { Name = "General Chat" },
Message = new MessageRequest { Text = "Channel name updated", UserId = "admin-user" }
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
await chatClient.UpdateChannelAsync("messaging", "general", new UpdateChannelRequest
{
Data = new ChannelInputRequest
{
Custom = new Dictionary<string, object> { { "name", "General Chat" } }
},
Message = new MessageRequest { Text = "Channel name updated", UserID = "admin-user" }
});
Key changes:
UpdateAsync()becomesUpdateChannelAsync()onChatClientChannelRequestbecomesChannelInputRequest; standard fields likeNamego in theCustomdictionary
Partial Update a Channel
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
await channelClient.PartialUpdateAsync("messaging", "general",
new PartialUpdateChannelRequest
{
Set = new Dictionary<string, object> { { "color", "blue" } },
Unset = new[] { "old_field" }
});
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
await chatClient.UpdateChannelPartialAsync("messaging", "general",
new UpdateChannelPartialRequest
{
Set = new Dictionary<string, object> { { "color", "blue" } },
Unset = new List<string> { "old_field" },
UserID = "admin-user"
});
Key changes:
PartialUpdateAsync()becomesUpdateChannelPartialAsync()PartialUpdateChannelRequestbecomesUpdateChannelPartialRequestUserIDis optional on the partial update request (set it server-side to attribute the change to a user)
Delete a Channel
Before (stream-chat-net):
using StreamChat.Clients;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
// Soft delete
await channelClient.DeleteAsync("messaging", "general");
// Batch delete
await channelClient.DeleteChannelsAsync(
new[] { "messaging:general", "messaging:support" }, hardDelete: true);
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
// Single delete
await chatClient.DeleteChannelAsync("messaging", "general");
// Batch delete
await chatClient.DeleteChannelsAsync(new DeleteChannelsRequest
{
Cids = new List<string> { "messaging:general", "messaging:support" },
HardDelete = true
});
Key changes:
DeleteAsync()becomesDeleteChannelAsync()- Batch delete uses
DeleteChannelsRequestwith aCidslist instead of positional parameters
Truncate a Channel
Before (stream-chat-net):
using StreamChat.Clients;
using StreamChat.Models;
var clientFactory = new StreamClientFactory("your-api-key", "your-api-secret");
var channelClient = clientFactory.GetChannelClient();
await channelClient.TruncateAsync("messaging", "general",
new TruncateOptions { HardDelete = true });
After (getstream-net):
using GetStream;
using GetStream.Models;
var client = new StreamClient(apiKey: "your-api-key", apiSecret: "your-api-secret");
var chatClient = new ChatClient(client);
await chatClient.TruncateChannelAsync("messaging", "general",
new TruncateChannelRequest { HardDelete = true });
Key changes:
TruncateAsync()becomesTruncateChannelAsync()TruncateOptionsbecomesTruncateChannelRequest