Class ExpandPolicy
Which navigation properties a client may expand from each entity type.
public static class ExpandPolicy
- Inheritance
-
ExpandPolicy
- Inherited Members
Remarks
Rules come from two places: AllowExpandAttribute and DenyExpandAttribute on the entity type, and the Allow<T>(params Expression<Func<T, object?>>[]) and Deny<T>(params Expression<Func<T, object?>>[]) methods here. The methods exist because a generated or scaffolded model cannot carry attributes - and because a registration overrides the attributes, so a deployment can tighten or relax what the model declares without editing it.
Each navigation is judged by this ladder, highest first:
- a registered Deny<T>(params Expression<Func<T, object?>>[]) refuses it;
- a registered Allow<T>(params Expression<Func<T, object?>>[]) list permits exactly its members and refuses everything else, shadowing the type's attributes entirely;
- a DenyExpandAttribute refuses it;
- an AllowExpandAttribute list permits exactly its members;
- otherwise DenyByDefault decides.
An allow-list always means "these and no others", whichever source it came from. So
Allow<Order>(o => o.Employee) does not merely lift a DenyExpand on
Employee - it makes Employee the only navigation expandable from Order.
With no rules at all nothing is refused, so adding this to an existing application changes nothing until you declare something or set DenyByDefault.
This governs expand only. A client can still reach a related entity through
select, which is checked by MaxDepth but not by this policy.
Properties
DenyByDefault
Whether a navigation with no rule about it is refused. False by default, so an existing application is unaffected until it opts in.
public static bool DenyByDefault { get; set; }
Property Value
Remarks
Setting this true makes every expandable navigation something you declared on purpose, which is the safer arrangement but needs the whole model reviewed first.
Methods
Allow<T>(params Expression<Func<T, object?>>[])
Permit exactly these navigations on T, refusing every other one.
public static void Allow<T>(params Expression<Func<T, object?>>[] navigations)
Parameters
navigationsExpression<Func<T, object>>[]Property expressions, as in
c => c.Orders.
Type Parameters
TThe entity type the navigations are declared on.
Exceptions
- ArgumentException
An expression is not a property access.
Deny<T>(params Expression<Func<T, object?>>[])
Refuse these navigations on T.
public static void Deny<T>(params Expression<Func<T, object?>>[] navigations)
Parameters
navigationsExpression<Func<T, object>>[]Property expressions, as in
o => o.Employee.
Type Parameters
TThe entity type the navigations are declared on.
Exceptions
- ArgumentException
An expression is not a property access.
FirstForbiddenHop(Type, string)
The leading part of path that policy refuses, or null if the whole path
is permitted.
public static string? FirstForbiddenHop(Type rootType, string path)
Parameters
rootTypeTypeThe entity type the path starts from.
pathstringA navigation path, dot- or slash-separated.
Returns
- string
The refused leading path, or null.
Remarks
The return value names the hop that was refused rather than the path that was asked for, so a refusal at the first hop does not disclose whether the rest of the path exists. A path that does not resolve against the model returns null: that is Validate(Type)'s to report, not this.
Reset()
Forget every registration, and the resolved rules. Intended for tests.
public static void Reset()
Validate(params Type[])
Resolve these types' rules now, so a contradiction is reported at startup rather than on whichever request first touches it.
public static void Validate(params Type[] entityTypes)
Parameters
entityTypesType[]The entity types to resolve.
Exceptions
- InvalidOperationException
A type names the same navigation in both an allow and a deny from the same source.