Error Cannot use a lambda expression
If you see an error like this:
Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type at System.Web.Compilation.AssemblyBuilder.Compile() at System.Web.Compilation.BuildProvidersCompiler.PerformBuild() at System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) at System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) at System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) at System.Web.Compilation.BuildManager.GetCompiledType(VirtualPath virtualPath) at ToSic.Sxc.Engines.RazorEngine.CreateWebPageInstance() in
It usually means that you tried to write LINQ code like a .First(...)
or .Select(...)
on an object, and the compiler can't be sure that you tried to write LINQ.
Background: Dynamic Code and Extension Methods
Razor is dynamically compiled code, and many objects like Content
are typed as dynamic
. Because of this, the compiler can't be sure what's in a dynamic
object, and also not what is in a Content.Tags
- since this too is regarded as dynamic
.
This is why you can't just write Content.Tags.First()
, because .First()
is an extension method which the compiler must find first - but it can't do that, since it doesn't know that Content.Tags
are of the type IEnumerable<...>
.
Solution #1 - use AsList(...)
2sxc 10.20 introduces AsList(...)
which the compiler knows is an IEnumerable. Unfortunately if the the compiler isn't sure about Content.Tags
, then it's also not sure about AsList(Content.Tags)
. This is a minor inconvenience, since AsList(...)
would figure things out, but Razor wants to be sure. So to use AsList()
for solving this problem, you'll need to write AsList(Content.Tags as object)
. That solves it.
Solution #2 - cast as IEnumerable<dynamic>
If you already know it's a list, you can also cast it as an IEnumerable<dynamic>
. Since IEnumerable<T>
is in the namespace System.Collections.Generic
you have 3 options:
Cast with full Namespace
This is what the compiler actually understands - but it's a bit long and hard to read:
var authors = (book.Authors as System.Collections.Generic.IEnumerable<dynamic>)
.Select(a => a.FirstName + " " + a.LastName);
Cast with @using
and IEnumerable<dynamic>
This is the same thing, just nicer to read:
@using System.Collections.Generic;
var authors = (book.Authors as IEnumerable<dynamic>)
.Select(a => a.FirstName + " " + a.LastName);
Cast with @using Dynlist = ...
This is the same thing, but the nicest, easiest to read method:
@using Dynlist = System.Collections.Generic.IEnumerable<dynamic>;
var authors = (book.Authors as Dynlist)
.Select(a => a.FirstName + " " + a.LastName);
Shortlink: https://go.2sxc.org/ErrLambda