You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Framework release scope follows CHANGELOG.md, with Product Search and MCP demonstrations showing the new capabilities in a distributed sample.
Framework enhancements
Single-use HTTP request builders: Send(method, uri) and Get/Post/Put/Patch/Delete shortcuts, WithJson for JSON and WithContent for explicit content. Body helpers are also available on HttpRequestMessage. Duplicate body assignments, repeated/concurrent execution and configuration after execution starts throw InvalidOperationException. PATCH does not imply JSON Merge Patch.
WithStatusResult / WithErrorStatus, including validated builders, intercept selected statuses before deserialization/validation. ValidatedHttpRequestBuilder<T> integrates response validation and automatic response disposal.
HttpResponseMessage.GetStringAsync() / ToStringResultAsync() and corresponding builder terminals provide raw response text, returning null for successful empty/204 responses.
Host-builder AddNamedHttpClient() / AddHttpClient() share idempotency, service discovery and resilience with typed clients. Separate configuration-section support augments SDK-owned named clients; existing registrations or callbacks can supply base addresses.
IEfDb.SqlQuery<T>(SqlStatement, params object[]) provides deferred, parameterized, composable scalar/unmapped EF queries using the existing context and transaction. CoreEx tenant/logical-delete filters are not automatic.
ReferenceDataOrchestrator.PrefetchAsync(IEnumerable<Type>) validates all types before loading, deduplicates requests and honors configured parallelism. Name-based prefetch checks cancellation immediately.
Added a predicate overload for validation DependsOn: a rule runs only when the dependency is non-default, has no validation error, and satisfies the additional condition.
Free-text $search across QueryArgs, configurable keyword/full-text/semantic/hybrid parsing, query schema, HTTP helpers, MVC/Minimal API metadata, NSwag and GraphQL-lite list roots. Keyword predicates execute through QueryExtensions.Where; repositories own ranked retrieval. Explicit $orderby is rejected for ranked search, and unconfigured search is rejected.
Behavior changes, fixes and maintenance
String-specific Required() rejects empty/whitespace strings as well as null with ValidationException.
HTTP registration binds resilience settings from the nested Resilience section rather than the parent client section.
GraphQL-lite search parsing errors preserve actionable details in extensions.messages["$search"] while retaining SEARCH_PARSE_ERROR. Regression coverage includes unsupported search, length/term limits, custom validation and aliased error paths.
WithQuery(QueryArgs) now forwards IsIncludeText and IsIncludeInactive.
Framework/template dependency updates include Aspire 13.6.1, EF/.NET servicing and FusionCache 2.9.0; PKCS 10.0.13 and MessagePack 2.5.307 overrides remain. Aspire 13.6.2 is not included.
Fixed CI restore's NU1902 failure by explicitly referencing MessagePack 2.5.307 in CoreEx.UnitTesting and sample/template MockHost. Central version entries alone do not pin transitive packages; no audit warning suppression was added.
SQL guidance now favors parameterized embedded resources for all application-owned static SQL; FromText is reserved for runtime-generated SQL.
Included scaffold command/skill descriptions and AppHost cleanup.
Product Search demonstration
Products-owned search exposed through REST and GraphQL-lite, with descriptions, structured filters and price constraints.
Exact pgvector cosine-distance retrieval using pinned local Ollama/Nomic embeddings behind an Application-owned adapter.
Independent PostgreSQL full-text retrieval and opt-in Hybrid RRF (k=60, up to 100 candidates per branch), eligible exact-SKU priority and deterministic ordering/paging.
Explicit rebuild/readiness and asynchronous outbox/relay/Service Bus/subscriber reconciliation across product creation, updates, activation and logical deletion, including stale-write/inference-race handling.
Fixed hybrid-search final candidate lookup on .NET 8 by using list-based membership rather than array Contains, avoiding unsupported span expressions during EF query evaluation.
Shared mountain-bike catalog, interactive runner search/setup, provenance and curated relevance evaluation. Historical v1/pre-SKU-rename v2 observations are not current-catalog quality gates; HNSW benchmarking remains future work.
Updated setup, architecture, lifecycle, evaluation and operational documentation.
MCP demonstration
Stateless Streamable HTTP Contoso.Mcp facade over real Products/Shopping APIs, wired through Aspire service discovery.
search_products forwards search text, category/subcategory/brand and inclusive price filters; get_product_search_options discovers live codes. MCP owns no database querying, embeddings or indexes.
Structured product and basket lifecycle tools: list/create/read baskets, add/update/remove items, discounts, shipping address and checkout through the existing inventory/outbox flow.
Direct tool coverage for forwarding, filtering, encoding, validation, errors and schema; SDK-driven HTTP E2E for discovery/basket lifecycle and separate real asynchronous product indexing coverage.
samples/docs/search.md includes MCP Inspector and Copilot CLI checks for discovery, structured filters and evidence-grounded responses. Deterministic tool/protocol tests are distinct from exploratory, model-dependent tool-selection evaluation.
The unauthenticated MCP host is local-development only; manual search checks are read-only and automated E2E setup requires disposable infrastructure.
Verification
CI passed for commit 13cab230, including the .NET 8 hybrid-search fix: https://github.com/Avanade/CoreEx/actions/runs/39486475035. This predates the latest GraphQL fix and documentation commit e9e32f2f; its CI result remains pending.
All 183 GraphQL unit tests passed locally on .NET 10 after the latest fix; the four new regression cases failed before the fix.
All 173 Products API tests passed locally on each of .NET 8, 9 and 10 after the hybrid-search fix (519 total).
143 HTTP unit tests passed during API finalization; 21 MCP ProductSearchToolTests passed after the dependency fix and AppHost edits.
Full solution restore passed with CI=true across target frameworks; multi-target CoreEx.UnitTesting build passed with zero warnings/errors.
Template validation passed 26/26 scenarios after the MockHost fix; patched MessagePack resolution was confirmed in CoreEx.UnitTesting and sample MockHost.
Full infrastructure E2E was not rerun locally for these final fixes; the successful CI run above provides the broader integration checks.
Changelog additions in this update
Added the DependsOn predicate overload. A rule now runs only when its dependency is non-default, has no validation error, and satisfies the additional predicate.
Added AI guidance and reference-data documentation for implicit code-to-concrete-type conversion, annotated contract code properties, and the distinction between conversion and validation.
Pinned local development, CI and publishing to the stable .NET SDK via global.json; updated nuget-publish.ps1 to build before packing and remove matching package versions from the local NuGet cache by default.
The latest commit 7a5eb50b adds DependsOn predicate support, tests and the changelog updates. All 116 CoreEx.Validation unit tests passed on .NET 10; CI for this latest commit has not yet completed.
Wire configurable keyword and ranked search through querying, HTTP, OpenAPI and GraphQL. Update the Products and MCP samples, tests and querying documentation.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Adopt DbEx 3.3.1 and patched dependency versions across framework and templates. Add opt-in net10 local builds, build-output cleanup, and leaner template validation. Preserve shared feed packages and publish only packages generated by the current run.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Capture reviewed catalog judgments and a real-model baseline, isolate evaluation data setup, and add manual/monthly reporting with retained artifacts.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Introduce independently maintained PostgreSQL full-text retrieval with exact-SKU priority and tuning-only relevance evaluation. Separate product query orchestration from CRUD and centralize server search-mode resolution.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Combine bounded lexical and semantic retrieval with reciprocal rank fusion. Expand the reviewed demo catalog and evaluation set, share catalog and reference data across demo setup, bootstrap Shopping through its sync adapter, and target the E2E Runner at net10. Normalize internal catalog SKUs without artificial DEMO prefixes.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Add search-session schema caching and catalog bootstrap progress, enable Hybrid in Aspire, and resolve local target frameworks early for Visual Studio.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Expose structured category, subcategory, brand and price filters on the MCP product search tool, add a live filter-options discovery tool, and cover the new contract with focused Aspire tests.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Pin patched MessagePack in CoreEx.UnitTesting and the sample/template MockHost so transitive consumers resolve 2.5.307. Include remaining scaffold descriptions and AppHost cleanup.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Use list-based candidate membership to avoid span expressions during EF query evaluation, and document the compatibility constraint.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
GraphQL search errors discard actionable validation details; preserve them before approval.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Surface query search parsing details in GraphQL errors
src/CoreEx.Data.GraphQL/GraphQLEngine.cs:367
QuerySearchParserException.Message is always the fallback "A query search parsing error occurred."; the actual reason (unsupported search, maximum length, or a custom validation failure) is stored in Messages. This branch bypasses MapValidationException and discards those details, leaving GraphQL callers unable to determine how to correct their search. Surface the stored message while retaining SEARCH_PARSE_ERROR.
Fixed the GraphQL search validation-detail finding from #189 (review) in commit e9e32f2. QuerySearchParserException now uses the shared validation-error mapper, preserving actionable details in extensions.messages["$search"] while retaining SEARCH_PARSE_ERROR and the root alias path. Added regression coverage for unsupported search, maximum length, term limits and custom validation; all four cases failed before the fix, and all 183 GraphQL unit tests passed afterward. README and v4.2.0 changelog are updated.
The latest automated review reports no open issues. The original finding was published in a review summary rather than an inline review thread, so GitHub provides no thread to mark resolved; this comment records its resolution.
Add expression-based validation factories and cached metadata fallbacks, distinguish request validation from domain business errors, and preserve DataResult mutation flags through mapping and event publication. Align samples, regression coverage, and AI guidance.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Use case-sensitive RFC 7396 member matching by default, recursively merge object patches, and avoid changes for absent-member removals. Preserve dictionary keys in serializer defaults and align regression coverage and documentation.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Update expected SQL Server, PostgreSQL and Redis health entry names to match their registered casing across sample and generated host tests.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Broad framework, persistence, build, and MCP changes require final human review; latest-commit CI remains pending.
No open issues 🎉
Review effort: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CoreEx v4.2.0
Framework release scope follows
CHANGELOG.md, with Product Search and MCP demonstrations showing the new capabilities in a distributed sample.Framework enhancements
Send(method, uri)andGet/Post/Put/Patch/Deleteshortcuts,WithJsonfor JSON andWithContentfor explicit content. Body helpers are also available onHttpRequestMessage. Duplicate body assignments, repeated/concurrent execution and configuration after execution starts throwInvalidOperationException. PATCH does not imply JSON Merge Patch.WithStatusResult/WithErrorStatus, including validated builders, intercept selected statuses before deserialization/validation.ValidatedHttpRequestBuilder<T>integrates response validation and automatic response disposal.HttpResponseMessage.GetStringAsync()/ToStringResultAsync()and corresponding builder terminals provide raw response text, returning null for successful empty/204 responses.AddNamedHttpClient()/AddHttpClient()share idempotency, service discovery and resilience with typed clients. Separate configuration-section support augments SDK-owned named clients; existing registrations or callbacks can supply base addresses.IEfDb.SqlQuery<T>(SqlStatement, params object[])provides deferred, parameterized, composable scalar/unmapped EF queries using the existing context and transaction. CoreEx tenant/logical-delete filters are not automatic.ReferenceDataOrchestrator.PrefetchAsync(IEnumerable<Type>)validates all types before loading, deduplicates requests and honors configured parallelism. Name-based prefetch checks cancellation immediately.DependsOn: a rule runs only when the dependency is non-default, has no validation error, and satisfies the additional condition.$searchacrossQueryArgs, configurable keyword/full-text/semantic/hybrid parsing, query schema, HTTP helpers, MVC/Minimal API metadata, NSwag and GraphQL-lite list roots. Keyword predicates execute throughQueryExtensions.Where; repositories own ranked retrieval. Explicit$orderbyis rejected for ranked search, and unconfigured search is rejected.Behavior changes, fixes and maintenance
Required()rejects empty/whitespace strings as well as null withValidationException.Resiliencesection rather than the parent client section.extensions.messages["$search"]while retainingSEARCH_PARSE_ERROR. Regression coverage includes unsupported search, length/term limits, custom validation and aliased error paths.DatabaseArgs.IsolationLevel; nested savepoints inherit parent isolation.WithQuery(QueryArgs)now forwardsIsIncludeTextandIsIncludeInactive.CoreEx.UnitTestingand sample/template MockHost. Central version entries alone do not pin transitive packages; no audit warning suppression was added.FromTextis reserved for runtime-generated SQL.Product Search demonstration
k=60, up to 100 candidates per branch), eligible exact-SKU priority and deterministic ordering/paging.Contains, avoiding unsupported span expressions during EF query evaluation.MCP demonstration
Contoso.Mcpfacade over real Products/Shopping APIs, wired through Aspire service discovery.search_productsforwards search text, category/subcategory/brand and inclusive price filters;get_product_search_optionsdiscovers live codes. MCP owns no database querying, embeddings or indexes.samples/docs/search.mdincludes MCP Inspector and Copilot CLI checks for discovery, structured filters and evidence-grounded responses. Deterministic tool/protocol tests are distinct from exploratory, model-dependent tool-selection evaluation.Verification
13cab230, including the .NET 8 hybrid-search fix: https://github.com/Avanade/CoreEx/actions/runs/39486475035. This predates the latest GraphQL fix and documentation commite9e32f2f; its CI result remains pending.CI=trueacross target frameworks; multi-targetCoreEx.UnitTestingbuild passed with zero warnings/errors.CoreEx.UnitTestingand sample MockHost.Changelog additions in this update
DependsOnpredicate overload. A rule now runs only when its dependency is non-default, has no validation error, and satisfies the additional predicate.global.json; updatednuget-publish.ps1to build before packing and remove matching package versions from the local NuGet cache by default.The latest commit
7a5eb50baddsDependsOnpredicate support, tests and the changelog updates. All 116 CoreEx.Validation unit tests passed on .NET 10; CI for this latest commit has not yet completed.