---
title: Projections
slug: cms-12/docs/projections
docTags: 
createdAt: 2026-08-10T15:56:00.000Z
---

Projecting search results lets you iterate over more suitable results for displaying search results and other listings. Also, because you select a subset of the indexed data, send only the required fields over the wire.

While the API supports returning instances of the actual type that is indexed (as long as you can instantiate it directly or configure the `Client` conventions), you should return matching objects as instances of a different type and project them. As with LINQ, you do this with a `Select` method.

The following code shows a projection from a type named `BlogPost` to a type named `SearchResult`.

```csharp
var result = client.Search<BlogPost>()
  .Select(x => new SearchResult {
    Title = x.Title,
      Author = x.Author.Name
  })
  .GetResult();
```

## Special methods

If you invoke a method in a select expression, it is invoked on the target object after fetching it from the search engine. If you changed the above example from `Title = x.Title` to `Title = x.Title.ToLower()`, the `Title` property is retrieved from the search engine, then `ToLower` executes on the client.

However, some extension methods get special treatment when parsed in a select expression.

- `AsHighlighted`  – When using this, you can project fragments from the source text into the result object. See [Highlight](docId\:VUFjI6VTgIvmQwNLx2_dj).
- `AsCropped` – Lets you retrieve only the beginning of a longer text field. `AsCropped` requires a single integer parameter, which controls the maximum length of the returned text. Unlike the `SubString` method, no exception is thrown if the actual text is shorter than the requested maximum length. Here is a sample usage.

```csharp
var result = client.Search<BlogPost>()
  .Select(x => new SearchResult {
    Title = x.Title.AsCropped(50),
      Author = x.Author.Name
  })
  .GetResult();
```

`AsCropped` tries to crop text to the specified maximum length without separating words.

:::hint{type="info"}
**Note**
Because the method uses a script on the search engine side, the execution is slower than projections that do not use it.
:::

## Limitations

The Optimizely Search & Navigation .NET client API's `Select` method is less powerful than the in-memory LINQ version, but it is powerful compared to most other LINQ providers.

The `Select` method's primary limitation is that it does not support projecting from complex types, except for enumerables of non-complex types. In the example above, you could not project the full `Author` object. However, you could project individual fields from the `Author` object to a complex object.

Another limitation is that the `Select` method cannot project user-defined functions or delegates. A user-defined function can request and load the entire object, including the binary attachment fields and nested objects. Avoid using user-defined functions or delegates. Instead, explicitly declare the projection in the select expression.

## Examples

The `Select` method works as expected if you are used to working with the LINQ equivalent, but remember the limitation of being unable to project from complex objects.

```csharp
var result = client.Search<BlogPost>()
  .Select(x => new {
    x.Title,
      AuthorName = x.Author.Name
  })
  .GetResult();

var result = client.Search<BlogPost>()
  .Select(x => new {
    x.Title,
      AuthorInfo = x.Author.Name + " id: " + x.Author.Id
  })
  .GetResult();

var result = client.Search<BlogPost>()
  .Select(x => x.Author.Id)
  .GetResult();
```

Avoid doing something like this.

```csharp
var result = client.Search<BlogPost>()
  .Select(x => new {
    x.Title,
      Parent = GetParent(x) // This is the problematic row.
  })
  .GetResult();
```

## Select and the fluent API

Call the `Select` method *after* calling the `searching` and `filtering` methods. Those methods depend on the type you are searching for rather than the type you are projecting search results to.
