[Canonical page](<https://docs.dhtmlx.com/planning-engine/net/api/project-roster/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Project.Roster

Reads the accepted state of a [`Project`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/project.md>) without skills: scheduled leaf tasks, resources and active assignments, in model order. Use it to build a custom [`Slot`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/slot.md>) list for [`SuggestAssignments`](<https://docs.dhtmlx.com/planning-engine/net/api/project-suggest-assignments.md>). Needs a solved project with no unsolved edits.

## Signature

```csharp
public Roster Roster()
```

Synchronous and CPU-only. Doesn't change the project's state.

## Returns

A new [`Roster`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/roster.md>) on each call.

## Errors

| Error | When |
|---|---|
| [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/project-exception.md>) `NoBaseline` | The project is unsolved, or has unsolved edits after [`Apply`](<https://docs.dhtmlx.com/planning-engine/net/api/project-apply.md>) |

## Example

Build one slot per scheduled task that has no assignment yet, open to every resource.

```csharp
using Plen;

var monday = Moment.FromYmdHm(2026, 8, 10, 8, 0) ?? throw new InvalidOperationException("invalid date");

var data = new ProjectData
{
    Tasks =
    [
        new TaskData("a") { StartDate = monday, Duration = 2.0 },
        new TaskData("b") { StartDate = monday, Duration = 2.0 },
    ],
    Resources = [new ResourceData { Id = "dev1" }, new ResourceData { Id = "dev2" }],
    Assignments = [new AssignmentData { Id = "x", Task = "a", Resource = "dev1", Value = 1.0 }],
};

var project = new Project();
project.Solve(data, new SolveOptions());

var roster = project.Roster();
var slots = roster.Tasks
    .Where(task => !roster.Assignments.Any(a => a.Task == task))
    .Select(task => new Slot($"slot-{task}", task, [.. roster.Resources]))
    .ToList();

var result = project.SuggestAssignments(slots, new SuggestOptions());
Console.WriteLine($"{slots.Count} slot(s), {result.Steps.Count} step(s)");
```

## Related

- [`Roster`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/roster.md>) - the returned snapshot
- [`Slot`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/slot.md>) - slots built from the roster
- [`Project.SuggestAssignments`](<https://docs.dhtmlx.com/planning-engine/net/api/project-suggest-assignments.md>) - the call that takes the slots
- [`SkillLayer.Slots`](<https://docs.dhtmlx.com/planning-engine/net/api/skill-layer-slots.md>) - builds slots from skills instead
- [Skills and requirements](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/skills-and-requirements.md>) - slots from workers and requirements
