Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
205 commits
Select commit Hold shift + click to select a range
621f986
Refactored Microsoft.Restier.Core + Tests
Apr 9, 2025
70fa1ae
Removed aspnet project
Apr 12, 2025
366f5cc
Most of the work done for aspnetcore
Apr 12, 2025
ac78d78
aspnetcore unit tests.
Apr 21, 2025
c8349e4
Add Entity Framework.
Apr 22, 2025
b7c585d
Added proper Chain of Responsibility logic for DI.
Apr 22, 2025
c7f0b65
Proper chaining of services in the core library.
Apr 23, 2025
6d888bb
Modelbuilder interface again and chained service
Apr 25, 2025
5f1e62e
Added ApiBaseTests
May 23, 2025
db17721
Added operationexecuter.
May 28, 2025
592eccb
Fix Query executor. Note: Todo count logic.
May 30, 2025
66628b7
Removed the RestierQueryExecutorOptions. Added properties to QueryReq…
May 30, 2025
de09242
Added unit tests for Model merger.
Jun 7, 2025
dc93ac7
Completely Rewritten model Building based on ChainsOfResponsibility
Jun 8, 2025
28efe4d
BreakDance integration
Jun 12, 2025
87763ea
Redesign Initialization API/DI.
Jun 17, 2025
0d02657
Added batch handler
Jun 24, 2025
6d7f725
Final DI Api design + Restoration of first feature tests.
Jun 24, 2025
5597926
Restored Restier Routing conventions.
Jun 29, 2025
c322a0b
Fix OData obsolete API build errors for ReturnType, Date, and TimeOfDay
Apr 13, 2026
3050fa1
Port Northwind sample to new Restier API surface
Apr 13, 2026
d4bc95f
Add user-secrets support for EF6 test connection strings
Apr 13, 2026
790a439
Clarify QueryModelReference test mock setup
Apr 13, 2026
d36e999
feat(routing): add RestierRouteMarker sentinel for route identification
Apr 14, 2026
13bf7cd
feat(routing): register RestierRouteMarker, remove convention registr…
Apr 14, 2026
d1b665d
feat(routing): add RestierRouteValueTransformer for dynamic OData pat…
Apr 14, 2026
0669222
feat(routing): add MapRestier() endpoint route builder extension
Apr 14, 2026
c48c282
feat(routing): register RestierRouteValueTransformer in all AddRestie…
Apr 14, 2026
d2a23c6
feat(routing): wire MapRestier() into test base and Northwind sample
Apr 14, 2026
3171086
refactor(routing): delete 8 template-based convention files
Apr 14, 2026
b416b6c
test: skip $filter path segment test pending RestierQueryBuilder support
Apr 14, 2026
1d13aea
test: add unit tests for RestierRouteValueTransformer
Apr 14, 2026
7d0c266
refactor(routing): return string directly from BuildBaseAddress
Apr 14, 2026
cba778d
test: add missing test cases for transformer edge cases
Apr 14, 2026
0c7ffec
test: add standalone $filter path segment integration test
Apr 14, 2026
3859e42
feat(query): implement FilterSegment handler in RestierQueryBuilder
Apr 14, 2026
8c2506c
test: enable $filter path segment tests now that handler is implemented
Apr 14, 2026
2d2b451
Enable AspNetCore feature tests
Apr 14, 2026
073c7e2
Constrain floating package versions below 10
Apr 14, 2026
5e6f1fa
fix: authorization tests and ODataPath IList cast in GetPathKeyValues
Apr 14, 2026
bc036d2
fix: remove mismatched routeName in EmptyEntitySetQueryReturns200Not4…
Apr 14, 2026
6031e13
fix: work around OData v9 $expand/$select incompatibility with EF6
Apr 14, 2026
9c1e4a3
fix: handle $metadata routing and remove dead old routing infrastructure
Apr 15, 2026
a87dd8e
fix: enable OData batch support and fix test ordering flakiness
Apr 15, 2026
ea47b63
fix: migrate ClaimsPrincipalAccessorTests to xUnit v3 and fix for vnext
Apr 15, 2026
9fcc445
fix: migrate FallbackTests to xUnit v3 and fix for vnext
Apr 15, 2026
5b16b19
fix: migrate RegressionTests to xUnit v3 and fix $count with $select/…
Apr 15, 2026
96086bb
fix: migrate AspNetCore root tests to xUnit v3 and restore AddChained…
Apr 15, 2026
af4ed33
docs: add design spec for dual EF6/EF Core testing
Apr 15, 2026
100b698
docs: fix ambiguity and note EF6 using bug in spec
Apr 15, 2026
f7aea45
docs: add implementation plan for dual EF6/EF Core testing
Apr 15, 2026
c8d3051
feat: add Microsoft.Restier.Tests.Shared.EntityFrameworkCore project
Apr 15, 2026
d397211
feat: add conditional namespaces to shared EF scenario files
Apr 15, 2026
4a3b4e4
feat: add SQL Server + in-memory fallback for EFCore test registration
Apr 15, 2026
1456089
feat: add EFCore project references and test collection definitions
Apr 15, 2026
bffe206
feat: refactor simple feature tests for dual EF6/EFCore testing
Apr 15, 2026
8d95d14
feat: refactor feature tests with helpers for dual EF6/EFCore
Apr 15, 2026
bfc8f95
feat: refactor MetadataTests for dual EF6/EFCore testing
Apr 15, 2026
dbda942
feat: refactor regression tests for dual EF6/EFCore testing
Apr 15, 2026
bb21849
fix: update namespace references and remove old collection definition
Apr 15, 2026
717e960
fix: fix EFCore test compatibility issues
Apr 15, 2026
b8bda36
fix: use TimeOnly for EFCore TimeOfDay converter and add provider-spe…
Apr 16, 2026
c535509
docs: add design spec for DateOnly/TimeOnly support
Apr 16, 2026
5e7f8f6
feat: add DateOnly/TimeOnly support to Restier type mapping pipeline
Apr 16, 2026
7dc30d1
test: add unit tests for DateOnly/TimeOnly type mappings
Apr 16, 2026
87bed98
fix: add collection attributes to regression tests to prevent concurr…
Apr 16, 2026
403b28d
fix: use CreateDatabaseIfNotExists to prevent concurrent drop errors
Apr 16, 2026
70271e1
test: convert old model tests from MSTest to xUnit v3
Apr 17, 2026
68efa53
refactor: remove obsolete conditional compilation directives
Apr 17, 2026
ea7ea3b
chore: remove legacy ASP.NET, Breakdance test, and obsolete test proj…
Apr 17, 2026
aea35a6
fix: update EntityFramework test project for vnext (net8/9, OData 8.x)
Apr 17, 2026
b7718be
fix: update EntityFrameworkCore test project for vnext (OData 8.x, fi…
Apr 17, 2026
0614e21
refactor: convert EFCore test files from MSTest to xUnit v3, fix remo…
Apr 17, 2026
9278643
refactor: convert ChangeSetPreparerTests from MSTest to xUnit v3
Apr 17, 2026
a73b8b7
fix: resolve EFCore test compilation errors for vnext API changes
Apr 17, 2026
ca26e7e
test: add EF6 ConvertToEfValue unit tests
Apr 17, 2026
3e7ac57
test: add EFModelBuilder happy-path test for standard context
Apr 17, 2026
20072a2
test: add EFModelMapper unit tests
Apr 17, 2026
b98868c
feat: include EntityFramework and EntityFrameworkCore test projects i…
Apr 17, 2026
7e5144a
feat: port Swagger project to ASP.NET Core OpenAPI and Swashbuckle 10.x
Apr 17, 2026
346639e
fix: use MapOpenApi route template instead of interpolated literal path
Apr 17, 2026
9bb58ae
fix: serve OpenAPI document via middleware instead of ASP.NET Core Op…
Apr 17, 2026
e494034
feat: add .NET 10 support and upgrade dependencies
Apr 17, 2026
cf550d3
fix: work around Breakdance 8.0 TestSetup infinite recursion bug
Apr 17, 2026
20895ac
fix: cherry-pick bug fixes from Restier 1.2 RTM on main
Apr 17, 2026
b73d516
docs: merge Restier 1.2 documentation from main
Apr 17, 2026
8d90012
docs: remove empty placeholder files and outdated operations doc
Apr 18, 2026
93de4a6
docs: update filters.md with current ASP.NET Core API patterns
Apr 18, 2026
8c4d9e8
docs: write Getting Started guide with ASP.NET Core and EF Core
Apr 18, 2026
359c3b9
docs: update index.md with current platform and component info
Apr 18, 2026
de4e4f7
docs: restore contributors table and link references in index.md
Apr 18, 2026
83bbbe6
docs: rewrite interceptors.md — fix incorrect descriptions, update to…
Apr 18, 2026
146d2e2
docs: update method-authorization.md with current API and xUnit patterns
Apr 18, 2026
58bc366
docs: rewrite model-building.md with current DI and attribute patterns
Apr 18, 2026
8a6f3f5
docs: add swagger.md documenting OpenAPI support
Apr 18, 2026
48a3125
docs: add operations.md documenting OData actions and functions
Apr 18, 2026
37fd75b
docs: add testing.md documenting Breakdance test framework
Apr 18, 2026
00276f0
docs: update temporal-types.md namespace references
Apr 18, 2026
ff695c1
docs: update in-memory-provider.md to ASP.NET Core patterns
Apr 18, 2026
29b83ad
docs: update contribution-guidelines.md with current tools and test c…
Apr 18, 2026
06cb6c8
docs: add links to operations, swagger, and testing docs in getting-s…
Apr 18, 2026
275006c
docs: add _site to gitignore and restore license.md with License.txt …
Apr 18, 2026
8e5bdc9
docs: add license link to index.md header
Apr 18, 2026
a442a64
docs: fix AddChainedService examples — Inner is wired automatically
Apr 18, 2026
de0f7ad
Merge origin/main (1.2 RTM) into feature/vnext
Apr 18, 2026
7667a9a
docs: add centralized filtering section to filters.md
Apr 18, 2026
0aadb10
fix: reject non-GET on $metadata/service doc, fix deserializer guard,…
Apr 18, 2026
7d8f413
fix: normalize PathBase in BuildBaseAddress to prevent double-slash URLs
Apr 18, 2026
db12da7
docs: add design spec for PostgreSQL sample vnext conversion
Apr 19, 2026
349f0de
docs: add implementation plan for PostgreSQL sample vnext conversion
Apr 19, 2026
5971fdd
chore: remove WeatherForecast template boilerplate from Postgres sample
Apr 19, 2026
ee74910
chore: align Postgres sample .csproj with Northwind vnext pattern
Apr 19, 2026
f0443e4
refactor: update RestierTestContextApi to vnext constructor signature
Apr 19, 2026
06721fd
refactor: rewrite Program.cs to vnext RESTier registration API
Apr 19, 2026
83f15b9
chore: add copyright headers, update .http file with OData endpoints
Apr 19, 2026
e5b6b5c
feat: add EF Core migration, seed data, user secrets, and launch prof…
Apr 19, 2026
ffed608
feat: add ChangeSetDependencyResolver for $ContentId batch references…
Apr 19, 2026
4630e71
fix: respect $ContentId dependencies in batch changeset requests (#762)
Apr 19, 2026
9f749b7
fix: address code review issues in batch $ContentId resolution
Apr 19, 2026
4db3feb
docs: document batch $ContentId dependency handling and TransactionSc…
Apr 19, 2026
0c6c3f6
fix: apply OnFilter interceptors to single navigation properties duri…
Apr 19, 2026
a3fc3e7
docs: add design spec for lower camelCase JSON property naming suppor…
Apr 19, 2026
d841a78
docs: address review findings in lower camelCase design spec (#549)
Apr 19, 2026
824dfdf
docs: add implementation plan for lower camelCase support (#549)
Apr 19, 2026
cdb387b
docs: rewrite implementation plan to address review findings (#549)
Apr 19, 2026
fb055cf
feat: add RestierNamingConvention enum (#549)
Apr 19, 2026
d1302fd
feat: add EdmClrPropertyMapper utility with unit tests (#549)
Apr 19, 2026
fb2e277
feat: add RestierNamingConvention parameter to AddRestierRoute overlo…
Apr 19, 2026
1dc0791
feat: call EnableLowerCamelCase in EFModelBuilder when configured (#549)
Apr 19, 2026
08341e8
feat: use EdmClrPropertyMapper in RestierQueryBuilder and update call…
Apr 19, 2026
22c6416
feat: normalize property dictionary keys to CLR names (#549)
Apr 19, 2026
5d8c410
feat: normalize ETag OriginalValues to CLR property names (#549)
Apr 19, 2026
769b556
feat: add RestierNamingConvention parameter to test helpers (#549)
Apr 19, 2026
bae947c
test: add BookCategory enum and ConcurrencyCheck to LibraryCard for n…
Apr 19, 2026
658bb67
test(wip): add naming convention integration tests — GET passes, POST…
Apr 19, 2026
307844a
feat: add RestierResourceDeserializer, enum parse fix, and 14 integra…
Apr 19, 2026
4fc1e63
fix: address code review findings in camelCase implementation (#549)
Apr 19, 2026
52a3502
fix: require SQL Server connection strings and improve database seeding
Apr 19, 2026
5d259e8
docs: add naming conventions page for camelCase configuration (#549)
Apr 19, 2026
43f37d7
docs: add optimistic concurrency page and fix ETag header handling (#…
Apr 22, 2026
fe2102f
docs: add DateOnly and TimeOnly to temporal types documentation (#549)
Apr 22, 2026
7c48182
docs: add design spec for deferred query materialization (#614)
Apr 22, 2026
f58c874
docs: revise deferred materialization spec after code review
Apr 22, 2026
28c0646
docs: add implementation plan for deferred query materialization (#614)
Apr 22, 2026
4f4505d
fix: defer materialization in DefaultQueryExecutor (#614)
Apr 22, 2026
9628e9a
fix: defer materialization in EFQueryExecutor (#614)
Apr 22, 2026
9e81943
style: add comment explaining EF6 materialization retention
Apr 22, 2026
220cb9d
refactor: remove CheckSubExpressionResult from DefaultQueryHandler (#…
Apr 22, 2026
45a9e1d
fix: add 404 detection for key-based requests in RestierController (#…
Apr 22, 2026
f543a7b
fix: dispose enumerator in ParentEntityExistsAsync
Apr 22, 2026
c21ae9e
fix: materialize explicitly in EFChangeSetInitializer.FindResource (#…
Apr 22, 2026
724b41d
docs: add performance page documenting EF6 materialization (#614)
Apr 22, 2026
929af84
fix: preserve entity element type in FindResource materialization
Apr 22, 2026
f76f7ad
fix: dispose enumerator in EnumerableExtensions.SingleOrDefault
Apr 22, 2026
de14797
fix: check last KeySegment in ParentEntityExistsAsync, not first
Apr 22, 2026
c4dba8a
test: add 204 and nested 404 tests for deferred materialization
Apr 22, 2026
4cf4c76
test: weaken 204 assertion to NotBe(404) for parallel TFM safety
Apr 22, 2026
ce90f1e
test: use isolated test data for 204 null-navigation test
Apr 22, 2026
2a65c93
docs: fix documentation issues from OData/RESTier#643
Apr 22, 2026
4cd3f47
docs: add design spec for deep insert/update and @odata.bind support
Apr 22, 2026
24fb66a
docs: revise deep operations spec addressing review findings
Apr 22, 2026
5dce590
docs: rev 3 deep operations spec addressing second review
Apr 22, 2026
90370b5
docs: rev 4 deep operations spec — version correctness and error flow
Apr 22, 2026
f294346
docs: add implementation plan for deep insert/update/bind support
Apr 22, 2026
db5dd4c
feat: add DataModificationItem tree structure, BindReference, and Dee…
Apr 23, 2026
ac47502
feat: add Review entity and explicit PublisherId FK for deep operatio…
Apr 23, 2026
799106b
feat: register DeepOperationSettings in route service container
Apr 23, 2026
50a87e7
feat: add protected helpers to DefaultChangeSetInitializer for nav pr…
Apr 23, 2026
3c5c60e
feat: add Phase 1 bind validation and Phase 2 nav prop wiring to EFCh…
Apr 23, 2026
34030d3
feat: add DeepOperationExtractor for nested entity extraction
Apr 23, 2026
d082b76
feat: integrate DeepOperationExtractor into RestierController.Post()
Apr 23, 2026
67e6630
fix: resolve DeepOperationSettings from per-route service container
Apr 23, 2026
b1fba23
test: add deep insert feature tests for EF6 and EFCore
Apr 23, 2026
bee8ca4
feat: add response shaping and deep update extraction to controller
Apr 23, 2026
5c443f5
fix: disable response shaping, use unique test IDs
Apr 23, 2026
7b1a23a
test: add deep update feature tests for EF6 and EFCore
Apr 23, 2026
a207b80
docs: add Phase 2 implementation plan for deep operations
Apr 23, 2026
fa3bdf7
docs: rewrite Phase 2 plan addressing review findings
Apr 23, 2026
3cab39d
docs: Phase 2 plan v3 — add design contracts and fix remaining gaps
Apr 23, 2026
ed275ca
docs: Phase 2 plan v4 — tighten classifier and reference contracts
Apr 23, 2026
a743b83
docs: Phase 2 plan v5 — fix final safety issues
Apr 23, 2026
e0e1a82
docs: Phase 2 plan v6 — final tightening for implementation readiness
Apr 23, 2026
a21f12c
docs: Phase 2 plan v7 — structural fixes for implementation readiness
Apr 23, 2026
d81bc8b
fix: MaxDepth off-by-one, null nav prop detection, raw key preservati…
Apr 28, 2026
dc8a095
fix: disable deep update extraction until classifier is implemented
Apr 28, 2026
ac6915a
test: add bind reference and bind-not-found feature tests
Apr 28, 2026
14d9032
docs: document OData-Version 4.01 limitation in deep operations spec
Apr 28, 2026
72ff0ac
feat: deep update classification with DeepUpdateClassifier and Relati…
Apr 28, 2026
46ad42c
fix: map relationship constraint DbUpdateException to HTTP 400
Apr 28, 2026
ed20095
test: add multi-level deep insert and move-child deep update tests
Apr 28, 2026
8b92c0c
fix: only expand NestedItems in response, not NavigationBindings
Apr 28, 2026
23bd87f
fix: single-nav null-unlink, 501 for unsupported FK, nullable FK check
Apr 28, 2026
6460f32
test: strengthen response expansion assertions and clarify bind test …
Apr 28, 2026
db2cd8b
test: strengthen response expansion assertions, add Phase 3 plan
Apr 28, 2026
6fcbca0
feat: re-enable response shaping in Post() and Update()
Apr 28, 2026
ab4ffb6
fix: resolve test failures from shared database pollution
Apr 28, 2026
a4137a4
feat: add FK-update logic to ClassifySingleNavProp for single-nav dee…
Apr 28, 2026
d90d45d
feat: add OData-Version 4.01 gating with clear error messages
Apr 29, 2026
99a7029
fix: improve OData 4.01 PATCH test quality
Apr 29, 2026
09c577a
test: add single-nav deep update test for insert with client-supplied…
Apr 29, 2026
289a721
fix: replace detached XML doc with plain comment, use UniqueId helper
Apr 29, 2026
c0203fb
test: add convention method tests for deep insert bind and deep update
Apr 29, 2026
0f67088
fix: use different seeded book in bind convention test
Apr 29, 2026
d110a43
fix: PATCH 4.01 test coverage and ExtractKeyValues default-value bug
Apr 29, 2026
9382b57
fix: FindTargetEntitySet phantom navigation source and no-key single-…
Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file added .DS_Store
Binary file not shown.
12 changes: 0 additions & 12 deletions .claude/settings.local.json

This file was deleted.

File renamed without changes.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,4 @@ ASALocalRun/
# MFractors (Xamarin productivity tool) working folder
.mfractor/
/docs/msdocs/.vscode
/docs/msdocs/_site/
107 changes: 107 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Microsoft RESTier is an OData V4 API development framework for building standardized RESTful services on .NET. It is the spiritual successor to WCF Data Services, providing convention-based query interception and data manipulation over Entity Framework.

## Build & Test Commands

```bash
# Build entire solution
dotnet build RESTier.slnx

# Run all tests
dotnet test RESTier.slnx

# Run a single test project
dotnet test test/Microsoft.Restier.Tests.Core/Microsoft.Restier.Tests.Core.csproj

# Run a specific test by name
dotnet test --filter "FullyQualifiedName~TestMethodName"

# Build a single project
dotnet build src/Microsoft.Restier.Core/Microsoft.Restier.Core.csproj
```

## Architecture

### Core Pipeline (Chain of Responsibility)

RESTier's central pattern is a **chain of responsibility** pipeline for both queries and submissions. Services implement `IChainedService<TService>` with an `Inner` property, composed via `IChainOfResponsibilityFactory`.

**Query pipeline** (`Microsoft.Restier.Core.Query`):
`IQueryExpressionSourcer` -> `IQueryExpressionAuthorizer` -> `IQueryExpressionExpander` -> `IQueryExpressionProcessor` -> `IQueryExecutor`
Orchestrated by `DefaultQueryHandler`.

**Submit pipeline** (`Microsoft.Restier.Core.Submit`):
`IChangeSetInitializer` -> `IChangeSetItemFilter` -> `IChangeSetItemAuthorizer` -> `IChangeSetItemValidator` -> `ISubmitExecutor`
Orchestrated by `DefaultSubmitHandler`.

### Convention-Based Interception

RESTier discovers interceptor methods by naming convention on `ApiBase` subclasses:
- `OnFiltering{EntitySet}()` / `OnInserting{Entity}()` / `OnValidating{Entity}()` etc.
- Implemented via `ConventionBasedQueryExpressionProcessor`, `ConventionBasedChangeSetItemFilter`, `ConventionBasedChangeSetItemValidator`

### Key Base Classes

- `ApiBase` - Base class for all RESTier APIs; subclass to define your API surface
- `EntityFrameworkApi<TContext>` - EF-specific base providing DbContext integration
- `RestierController : ODataController` - Handles OData HTTP requests in ASP.NET Core

### Project Layout

| Directory | Purpose |
|-----------|---------|
| `src/Microsoft.Restier.Core` | Core abstractions, pipelines, conventions, DI |
| `src/Microsoft.Restier.AspNetCore` | ASP.NET Core integration, routing, controller |
| `src/Microsoft.Restier.EntityFramework` | Entity Framework 6.x support |
| `src/Microsoft.Restier.EntityFrameworkCore` | Entity Framework Core support |
| `src/Microsoft.Restier.EntityFramework.Shared` | Shared EF code (shared project, not NuGet) |
| `src/Microsoft.Restier.Breakdance` | In-memory testing framework |
| `src/Microsoft.Restier.AspNetCore.Swagger` | Swagger/OpenAPI generation |

### Dependency Injection

Uses `Microsoft.Extensions.DependencyInjection` with per-route service containers. Service registration extensions are in `Microsoft.Restier.Core.DependencyInjection` and `Microsoft.Restier.AspNetCore.Extensions`.

## Code Conventions

- **Targets:** .NET 8.0, .NET 9.0, and .NET Framework 4.8
- **Warnings as errors** enabled globally
- **Implicit usings disabled** - all `using` directives must be explicit
- **Nullable reference types disabled**
- **Strong name signing** with `restier.snk`
- **Allman brace style**, prefer `var`, prefer curly braces even for single-line blocks
- **InternalsVisibleTo** is auto-configured from source to matching test project

## Test Conventions

- **Framework:** xUnit v3, FluentAssertions (AwesomeAssertions), NSubstitute
- **Project naming:** `X` -> `X.Tests` (e.g., `Microsoft.Restier.Core` -> `Microsoft.Restier.Tests.Core`)
- **File naming:** `X/Y/Z/A.cs` -> `X.Tests/Y/Z/ATests.cs`
- **Namespace:** must match folder path (e.g., `Microsoft.Restier.Tests.Core.Convention`)
- **Integration/scenario tests** go in `X.Tests/IntegrationTests` or `X.Tests/ScenarioTests`

## Documentation

Documentation lives in `docs/msdocs/` and is built with **docfx** (not mkdocs, despite the legacy `mkdocs.yml`).

```bash
# Build docs (installs docfx as .NET global tool if missing)
docs/msdocs/build.sh

# Serve locally for preview
docfx serve docs/msdocs/_site
```

The navigation structure is defined in `docs/mkdocs.yml` (legacy) and `docs/msdocs/toc.yml` / `docs/msdocs/docfx.json`.

## Key Dependencies

- Microsoft.OData.Core / Microsoft.OData.Edm (8.x)
- Microsoft.OData.ModelBuilder (2.x)
- Microsoft.AspNetCore.OData (9.x)
- EntityFramework 6.5.x / EntityFrameworkCore 8.x-10.x
55 changes: 34 additions & 21 deletions src/Directory.Build.props → Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<IsBenchmarkProject Condition="$(MSBuildProjectName.EndsWith('.Performance'))">true</IsBenchmarkProject>
<IsTestProject Condition="$(MSBuildProjectName.ToLower().Contains('.tests.'))">true</IsTestProject>
<IsTestSharedProject Condition="$(MSBuildProjectName.ToLower().Contains('.tests.shared'))">true</IsTestSharedProject>
<IsTestAssetProject Condition="$(RepoRelativeProjectDir.ToLower().Contains('testassets'))">true</IsTestAssetProject>
<IsSampleProject Condition="$(MSBuildProjectName.ToLower().Contains('.samples.'))">true</IsSampleProject>
<IsTemplateProject Condition="$(MSBuildProjectName.ToLower().Contains('.templates.'))">true</IsTemplateProject>
Expand Down Expand Up @@ -81,19 +82,13 @@
<!-- Suppress warnings about pre-release packages -->
<NoWarn>$(NoWarn);NU5104</NoWarn>

</PropertyGroup>
<!-- Suppress .NET 10 package pruning warnings for multi-targeted packages that are in-box on net10.0 -->
<NoWarn>$(NoWarn);NU1510</NoWarn>

<!-- Base settings for all test projects -->
<PropertyGroup Condition=" $(IsTestProject) == 'true' ">
<NoWarn>$(NoWarn);CA1001;CA1031;CA1062;CA1301;CA1303;AC1307;CA1707;CA1716;CA1801;CA1806;CA1819;CA1822;CA1825;CA2000;CA2007;CA2227;CA2234</NoWarn>
<IsPackable>false</IsPackable>
</PropertyGroup>

<!-- Use VSTest for all test projects to support both net48 and modern .NET in the same test run.
MSTest 4.x with EnableMSTestRunner=true would enable Microsoft.Testing.Platform,
but that conflicts with net48 projects which cannot use MTP. -->
<PropertyGroup Condition=" $(IsTestProject) == 'true' ">
<EnableMSTestRunner>false</EnableMSTestRunner>
<NoWarn>$(NoWarn);CA1001;CA1031;CA1062;CA1301;CA1303;AC1307;CA1707;CA1716;CA1801;CA1806;CA1819;CA1822;CA1825;CA2000;CA2007;CA2227;CA2234</NoWarn>
</PropertyGroup>

<PropertyGroup Condition=" $(IsSampleProject) == 'true' ">
Expand All @@ -108,26 +103,44 @@

<PropertyGroup>
<StandardTestTfms>net48</StandardTestTfms>
<RestierBreakdanceVersion>[8.0.0, 9.0.0)</RestierBreakdanceVersion>
<RestierEasyAfVersion>[4.0.0, 5.0.0)</RestierEasyAfVersion>
<RestierNet9DependencyInjectionVersion>[9.*, 10.0.0)</RestierNet9DependencyInjectionVersion>
<RestierNet9EntityFrameworkVersion>[9.*, 10.0.0)</RestierNet9EntityFrameworkVersion>
<RestierNet9SystemTextJsonVersion>[9.*, 10.0.0)</RestierNet9SystemTextJsonVersion>
<RestierNet9UserSecretsVersion>[9.*, 10.0.0)</RestierNet9UserSecretsVersion>
<RestierNet9AspNetCoreTestHostVersion>[9.*, 10.0.0)</RestierNet9AspNetCoreTestHostVersion>
<RestierNet10DependencyInjectionVersion>[10.*, 11.0.0)</RestierNet10DependencyInjectionVersion>
<RestierNet10EntityFrameworkVersion>[10.*, 11.0.0)</RestierNet10EntityFrameworkVersion>
<RestierNet10SystemTextJsonVersion>[10.*, 11.0.0)</RestierNet10SystemTextJsonVersion>
<RestierNet10UserSecretsVersion>[10.*, 11.0.0)</RestierNet10UserSecretsVersion>
<RestierNet10AspNetCoreTestHostVersion>[10.*, 11.0.0)</RestierNet10AspNetCoreTestHostVersion>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(RestierNet9DependencyInjectionVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="$(RestierNet9UserSecretsVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(RestierNet9UserSecretsVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="$(RestierNet9UserSecretsVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="$(RestierNet9UserSecretsVersion)" PrivateAssets="All" />
<PackageReference Include="System.Text.Json" Version="$(RestierNet9SystemTextJsonVersion)" PrivateAssets="All" />
</ItemGroup>


<ItemGroup Condition=" $(IsTestProject) != 'true' AND $(IsSampleProject) != 'true'">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.*" PrivateAssets="All" />

<InternalsVisibleTo Include="$(AssemblyName.Replace('Microsoft.Restier.', 'Microsoft.Restier.Tests.')), $(StrongNamePublicKey)" />
</ItemGroup>

<ItemGroup Condition=" $(IsTestProject) == 'true' and $(IsSampleProject) != 'true'">
<ItemGroup Condition=" $(IsTestProject) == 'true' and $(IsSampleProject) != 'true' and $(IsTestSharedProject) != 'true'">
<PackageReference Include="coverlet.collector" Version="6.*" />
<PackageReference Include="FluentAssertions" Version="6.*" PrivateAssets="All" />
<PackageReference Include="FluentAssertions.Analyzers" Version="0.*" PrivateAssets="All" />
<PackageReference Include="MSTest" Version="4.*" />

<!-- Enable parallel test execution in MSTest 4 and later. -->
<AssemblyAttribute Include="Microsoft.VisualStudio.TestTools.UnitTesting.Parallelize">
<_Parameter1>Workers = 1</_Parameter1>
<_Parameter1_IsLiteral>true</_Parameter1_IsLiteral>
<_Parameter2>Scope = Microsoft.VisualStudio.TestTools.UnitTesting.ExecutionScope.MethodLevel</_Parameter2>
<_Parameter2_IsLiteral>true</_Parameter2_IsLiteral>
</AssemblyAttribute>
<PackageReference Include="AwesomeAssertions" Version="8.*" PrivateAssets="All" />
<PackageReference Include="AwesomeAssertions.Analyzers" Version="0.*" PrivateAssets="All" />
<PackageReference Include="xunit.v3" Version="3.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
<PackageReference Include="NSubstitute" Version="5.3.0"></PackageReference>
</ItemGroup>

<ItemGroup>
Expand Down
40 changes: 40 additions & 0 deletions RESTier.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<Solution>
<Folder Name="/Solution Items/">
<File Path="NuGet.Config" />
<File Path="README.md" />
<File Path=".editorconfig" />
<File Path="Directory.Build.props" />
<File Path="dotnet-logo.png" />
</Folder>
<Folder Name="/src/" Id="02ea681e-c7d8-13c7-8484-4ac65e1b71e8">
<Project Path="src/Microsoft.Restier.Breakdance/Microsoft.Restier.Breakdance.csproj" />
<Project Path="src/Microsoft.Restier.Core/Microsoft.Restier.Core.csproj" />
</Folder>
<Folder Name="/src/EntityFramework/" Id="a290b16b-6f9e-4703-8c01-135831ad90df">
<Project Path="src/Microsoft.Restier.EntityFramework.Shared/Microsoft.Restier.EntityFramework.Shared.shproj" Id="83ad7aa8-9ed8-4b9f-966a-73ce9cae51c6" />
<Project Path="src/Microsoft.Restier.EntityFramework/Microsoft.Restier.EntityFramework.csproj" />
<Project Path="src/Microsoft.Restier.EntityFrameworkCore/Microsoft.Restier.EntityFrameworkCore.csproj" />
</Folder>
<Folder Name="/src/Samples/">
<Project Path="src/Microsoft.Restier.Samples.Northwind.AspNetCore/Microsoft.Restier.Samples.Northwind.AspNetCore.csproj" />
<Project Path="src/Microsoft.Restier.Samples.Postgres.AspNetCore/Microsoft.Restier.Samples.Postgres.AspNetCore.csproj" />
</Folder>
<Folder Name="/src/Web/" Id="bf61c3f1-7c7e-4515-8b51-14b374a034f9">
<Project Path="src/Microsoft.Restier.AspNetCore.Swagger/Microsoft.Restier.AspNetCore.Swagger.csproj" />
<Project Path="src/Microsoft.Restier.AspNetCore/Microsoft.Restier.AspNetCore.csproj" />
</Folder>
<Folder Name="/test/" Id="67e76b39-b345-4061-b1a8-31b95b6f83a8">
<Project Path="test/Microsoft.Restier.Tests.Core/Microsoft.Restier.Tests.Core.csproj" />
<Project Path="test/Microsoft.Restier.Tests.Shared/Microsoft.Restier.Tests.Shared.csproj" />
</Folder>
<Folder Name="/test/EntityFramework/" Id="b45d57df-5e57-4cf8-9ff8-86a03f39bb09">
<Project Path="test/Microsoft.Restier.Tests.EntityFramework/Microsoft.Restier.Tests.EntityFramework.csproj" />
<Project Path="test/Microsoft.Restier.Tests.EntityFrameworkCore/Microsoft.Restier.Tests.EntityFrameworkCore.csproj" />
<Project Path="test/Microsoft.Restier.Tests.Shared.EntityFramework/Microsoft.Restier.Tests.Shared.EntityFramework.csproj" />
<Project Path="test/Microsoft.Restier.Tests.Shared.EntityFrameworkCore/Microsoft.Restier.Tests.Shared.EntityFrameworkCore.csproj" />
</Folder>
<Folder Name="/test/Web/" Id="ae160b58-fb2d-4b9f-9357-8c7648381b95">
<Project Path="test/Microsoft.Restier.Tests.AspNetCore.Swagger/Microsoft.Restier.Tests.AspNetCore.Swagger.csproj" />
<Project Path="test/Microsoft.Restier.Tests.AspNetCore/Microsoft.Restier.Tests.AspNetCore.csproj" />
</Folder>
</Solution>
Binary file added docs/.DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pages:
- 'Method Authorization': 'server/method-authorization.md'
- 'Interceptors': 'server/interceptors.md'
- 'Model Building': 'server/model-building.md'
- 'Naming Conventions': 'server/naming-conventions.md'
- 'Optimistic Concurrency': 'server/concurrency.md'
- Extending RESTier:
- 'Temporal Types': 'extending-restier/temporal-types.md'
- 'In-Memory Provider': 'extending-restier/in-memory-provider.md'
Expand Down
Binary file added docs/msdocs/.DS_Store
Binary file not shown.
23 changes: 23 additions & 0 deletions docs/msdocs/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Ensure .NET global tools are on PATH
export PATH="$PATH:$HOME/.dotnet/tools"

# Check if docfx is available
if ! command -v docfx &>/dev/null; then
echo "docfx not found. Installing as a .NET global tool..."
dotnet tool install -g docfx
fi

# Clean previous output to avoid stale file warnings
rm -rf "$SCRIPT_DIR/_site"

echo "Building docs..."
docfx build "$SCRIPT_DIR/docfx.json" --output "$SCRIPT_DIR/_site"

echo ""
echo "Build complete. Output is in: $SCRIPT_DIR/_site"
echo "To preview locally, run: docfx serve $SCRIPT_DIR/_site"
1 change: 0 additions & 1 deletion docs/msdocs/clients/dot-net-standard.md

This file was deleted.

1 change: 0 additions & 1 deletion docs/msdocs/clients/dot-net.md

This file was deleted.

1 change: 0 additions & 1 deletion docs/msdocs/clients/typescript.md

This file was deleted.

19 changes: 8 additions & 11 deletions docs/msdocs/contribution-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ before you work on the pull request. After the RESTier team has reviewed this is
to "accepting pull request", you can work on the code change.

### Prepare Tools
[Atom](https://atom.io/) with package [atom-beautify](https://atom.io/packages/atom-beautify) and
[markdown-toc](https://atom.io/packages/markdown-toc) is recommended to edit the document.
[MarkdownPad](http://www.markdownpad.com/) can also be used to edit the document.<br />
Visual Studio 2015 is recommended for code contribution.
Visual Studio 2022 or later is recommended for code contribution. VS Code and JetBrains Rider also work well.

### Steps to create a pull request
These are the recommended steps to create a pull request:<br />
Expand All @@ -36,28 +33,28 @@ These are the recommended steps to create a pull request:<br />
3. Add a git remote to upstream for local repository with command _git remote add upstream
[https://github.com/OData/RESTier.git](https://github.com/OData/RESTier.git)_
4. Make code changes and add test cases, refer Test specification section for more details about test
5. Test the changed codes with one-click build and test script
5. Build and test the changes with `dotnet build RESTier.slnx && dotnet test RESTier.slnx`
6. Commit changed code to local repository with clear message
7. Rebase the code to upstream via command _git pull --rebase upstream master_ and resolve conflicts
7. Rebase the code to upstream via command _git pull --rebase upstream main_ and resolve conflicts
if there is any then continue rebase via command _git pull --rebase continue_
8. Push local commit to the forked repository
9. Create pull request from forked repository Web console via comparing with upstream.
10. Complete a Contributor License Agreement (CLA), refer below section for more details.
11. Pull request will be reviewed by Microsoft OData team
12. Address comments and revise code if necessary
13. Commit the changes to local repository or amend existing commit via command _git commit --amend_
14. Rebase the code with upstream again via command _git pull --rebase upstream master_ and resolve
14. Rebase the code with upstream again via command _git pull --rebase upstream main_ and resolve
conflicts if there is any then continue rebase via command _git pull --rebase continue_
15. Test the changed codes with one-click build and test script again
15. Build and test the changes again with `dotnet build RESTier.slnx && dotnet test RESTier.slnx`
16. Push changes to the forked repository and use _--force_ option if existing commit is amended
17. Microsoft OData team will merge the pull request into upstream

### Test specification
All tests need to be written with xUnit. Here are some rules to follow when you are organizing the
All tests need to be written with **xUnit v3**. Use **FluentAssertions** for assertions and **NSubstitute** for mocking. Here are some rules to follow when you are organizing the
test code:

- **Project name correspondence** (`X -> X.Tests`). For instance, all the test code of the `Microsoft.Restier.Core` project should be placed in the `Microsoft.Restier.Core.Tests` project. Path and file name correspondence. (`X/Y/Z/A.cs -> X.Tests/Y/Z/ATests.cs`). For example, the test code of the `ConventionBasedApiModelBuilder` class (in the `Microsoft.Restier.Core/Convention/ConventionBasedApiModelBuilder.cs` file) should be placed in the `Microsoft.Restier.Core.Tests/Convention/ConventionBasedApiModelBuilderTests.cs` file.
- **Namespace correspondence** (`X.Tests/Y/Z -> X.Tests.Y.Z`). The namespace of the file should strictly follow the path. For example, the namespace of the `ConventionBasedApiModelBuilderTests.cs` file should be `Microsoft.Restier.Core.Tests.Convention`.
- **Project name correspondence** (`Microsoft.Restier.X` -> `Microsoft.Restier.Tests.X`). For instance, all the test code of the `Microsoft.Restier.Core` project should be placed in the `Microsoft.Restier.Tests.Core` project. Path and file name correspondence. (`X/Y/Z/A.cs -> X.Tests/Y/Z/ATests.cs`). For example, the test code of the `ConventionBasedApiModelBuilder` class (in the `Microsoft.Restier.Core/Convention/ConventionBasedApiModelBuilder.cs` file) should be placed in the `Microsoft.Restier.Tests.Core/Convention/ConventionBasedApiModelBuilderTests.cs` file.
- **Namespace correspondence** (`X.Tests/Y/Z -> X.Tests.Y.Z`). The namespace of the file should strictly follow the path. For example, the namespace of the `ConventionBasedApiModelBuilderTests.cs` file should be `Microsoft.Restier.Tests.Core.Convention`.
- **Utility classes**. The file for a utility class can be placed at the same level of its user or a shared level that is visible to all its users. But the file name must **NOT** be ended with `Tests` to avoid any confusion.
- **Integration and scenario tests**. Those tests usually involve multiple modules and have some specific scenarios. They should be placed separately in `X.Tests/IntegrationTests` and `X.Tests/ScenarioTests`. There is no hard requirement of the folder structure for those tests. But they should be organized logically and systematically as possible.

Expand Down
Loading
Loading