Feature Discovery

Why it exists

Some MRX behaviors are opt-in per controller or action — Disambiguation is one example. A client that doesn't know whether a given endpoint has a feature enabled would have to either hardcode that assumption per endpoint or guess from response shape. Feature Discovery lets a client ask the server directly, for a specific route and HTTP method: "which MRX features are enabled here?" — instead of guessing or hardcoding.

Setting it up

Install the package:

dotnet add package MRX.FeatureDiscovery

Then, in Program.cs:

builder.Services.AddMrxFeatureDiscovery();
// ...
app.UseMrxFeatureDiscovery();

AddMrxFeatureDiscovery registers the discovery controller as an MVC application part along with the RouteProbe service it depends on; UseMrxFeatureDiscovery maps controllers so the discovery endpoint is actually reachable.

Querying it

The discovery endpoint responds to OPTIONS requests on any path, with the probed HTTP method passed via the X-Probe-Method request header:

OPTIONS /orders/42 HTTP/1.1
X-Probe-Method: PUT
HTTP/1.1 200 OK
Content-Type: application/json

{ "features": ["ERROR_KEY_DISAMBIGUATION"] }

If no registered route matches the probed path and method, the endpoint returns 404 Not Found.

How a match is resolved

RouteProbe lazily builds and caches a list of every non-catch-all route, each paired with a compiled TemplateMatcher as a MatchedRoute so that a probed path can be tested against it without re-parsing the route template on every request. To resolve a probe, it walks that cached list looking for the first route whose template matches the probed path and whose HttpMethodActionConstraint metadata includes the probed method.

Once a matching RouteEndpoint is found, the controller reads every IFeatureDescriptor attached to it as endpoint metadata and returns their feature names in a FeatureDiscoveryResponse. This is the same mechanism that surfaces [Disambiguate]: the attribute implements IFeatureDescriptor, so simply applying it to a controller or action is enough for it to be picked up here — nothing else needs to be registered for a feature to become discoverable this way.

Exposing your own features

Because feature discovery works off any IFeatureDescriptor attached as endpoint metadata, you can make your own opt-in behaviors discoverable the same way [Disambiguate] is: implement IFeatureDescriptor on an attribute (or any other type usable as endpoint metadata) and apply it to the relevant controllers or actions. No changes to MRX.FeatureDiscovery itself are required — the discovery endpoint reads whatever IFeatureDescriptor metadata is present on the matched endpoint at request time.