From 4dfbeaba90dacac48b42bf3c5de716deb0d3d36e Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sun, 14 May 2023 23:05:35 +0200 Subject: [PATCH 01/41] Fixed NoEntityFrameworkExample: block write endpoints --- src/Examples/NoEntityFrameworkExample/Models/Person.cs | 3 ++- src/Examples/NoEntityFrameworkExample/Models/Tag.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Examples/NoEntityFrameworkExample/Models/Person.cs b/src/Examples/NoEntityFrameworkExample/Models/Person.cs index 47a7f4da9a..2e7d4a02ab 100644 --- a/src/Examples/NoEntityFrameworkExample/Models/Person.cs +++ b/src/Examples/NoEntityFrameworkExample/Models/Person.cs @@ -1,12 +1,13 @@ using System.ComponentModel.DataAnnotations.Schema; using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; namespace NoEntityFrameworkExample.Models; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -[Resource] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.Query)] public sealed class Person : Identifiable { [Attr] diff --git a/src/Examples/NoEntityFrameworkExample/Models/Tag.cs b/src/Examples/NoEntityFrameworkExample/Models/Tag.cs index 425fe0923f..4a6ae70f49 100644 --- a/src/Examples/NoEntityFrameworkExample/Models/Tag.cs +++ b/src/Examples/NoEntityFrameworkExample/Models/Tag.cs @@ -1,12 +1,13 @@ using System.ComponentModel.DataAnnotations; using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; namespace NoEntityFrameworkExample.Models; [UsedImplicitly(ImplicitUseTargetFlags.Members)] -[Resource] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.Query)] public sealed class Tag : Identifiable { [Attr] From 793570f95b20861e73259cdef596be2931e64250 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Thu, 18 May 2023 13:41:04 +0200 Subject: [PATCH 02/41] Package updates --- .config/dotnet-tools.json | 8 ++++---- Directory.Build.props | 2 +- docs/build-dev.ps1 | 3 +++ docs/docfx.json | 2 +- test/TestBuildingBlocks/TestBuildingBlocks.csproj | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 40d3ba4893..ad89a48ac6 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,13 +3,13 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2023.1.0", + "version": "2023.1.2", "commands": [ "jb" ] }, "regitlint": { - "version": "6.3.10", + "version": "6.3.11", "commands": [ "regitlint" ] @@ -21,13 +21,13 @@ ] }, "dotnet-reportgenerator-globaltool": { - "version": "5.1.19", + "version": "5.1.20", "commands": [ "reportgenerator" ] }, "docfx": { - "version": "2.62.2", + "version": "2.67.1", "commands": [ "docfx" ] diff --git a/Directory.Build.props b/Directory.Build.props index af2fb7ac5b..54b8a4d10d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -35,6 +35,6 @@ 3.2.* 4.18.* - 17.5.* + 17.6.* diff --git a/docs/build-dev.ps1 b/docs/build-dev.ps1 index bdd13d16b8..6bff0e5fcb 100644 --- a/docs/build-dev.ps1 +++ b/docs/build-dev.ps1 @@ -37,6 +37,9 @@ if (-Not $NoBuild -Or -Not (Test-Path -Path _site)) { Invoke-Expression ./generate-examples.ps1 } +dotnet tool restore +VerifySuccessExitCode + dotnet docfx ./docfx.json VerifySuccessExitCode diff --git a/docs/docfx.json b/docs/docfx.json index 7fdafa0fe5..1d0e192ac2 100644 --- a/docs/docfx.json +++ b/docs/docfx.json @@ -40,7 +40,7 @@ "dest": "_site", "globalMetadataFiles": [], "fileMetadataFiles": [], - "template": [ "default" ], + "template": [ "default", "modern" ], "postProcessors": [], "noLangKeyword": false, "keepFileLink": false, diff --git a/test/TestBuildingBlocks/TestBuildingBlocks.csproj b/test/TestBuildingBlocks/TestBuildingBlocks.csproj index 46193372a8..bec40e7ed7 100644 --- a/test/TestBuildingBlocks/TestBuildingBlocks.csproj +++ b/test/TestBuildingBlocks/TestBuildingBlocks.csproj @@ -10,7 +10,7 @@ - + From a1cf3ab30659f1f25c80d5e5d890c34ad0adb3ac Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Thu, 18 May 2023 16:12:41 +0200 Subject: [PATCH 03/41] use mermaid diagrams --- docs/internals/queries.md | 5 ++- docs/usage/extensibility/services.md | 64 ++++++++++++---------------- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/docs/internals/queries.md b/docs/internals/queries.md index 76f062c233..198a1659a2 100644 --- a/docs/internals/queries.md +++ b/docs/internals/queries.md @@ -4,8 +4,9 @@ _since v4.0_ The query pipeline roughly looks like this: -``` -HTTP --[ASP.NET]--> QueryString --[JADNC:QueryStringParameterReader]--> QueryExpression[] --[JADNC:ResourceService]--> QueryLayer --[JADNC:Repository]--> IQueryable --[Entity Framework Core]--> SQL +```mermaid +flowchart TB +A[HTTP] -->|ASP.NET| B(QueryString) -->|JADNC:QueryStringParameterReader| C("QueryExpression[]") -->|JADNC:ResourceService| D(QueryLayer) -->|JADNC:Repository| E(IQueryable) -->|Entity Framework Core| F[(SQL)] ``` Processing a request involves the following steps: diff --git a/docs/usage/extensibility/services.md b/docs/usage/extensibility/services.md index 6cdea8b783..90dea1352b 100644 --- a/docs/usage/extensibility/services.md +++ b/docs/usage/extensibility/services.md @@ -81,42 +81,34 @@ In some cases it may be necessary to only expose a few actions on a resource. Fo This interface hierarchy is defined by this tree structure. -``` -IResourceService -| -+-- IResourceQueryService -| | -| +-- IGetAllService -| | GET / -| | -| +-- IGetByIdService -| | GET /{id} -| | -| +-- IGetSecondaryService -| | GET /{id}/{relationship} -| | -| +-- IGetRelationshipService -| GET /{id}/relationships/{relationship} -| -+-- IResourceCommandService - | - +-- ICreateService - | POST / - | - +-- IUpdateService - | PATCH /{id} - | - +-- IDeleteService - | DELETE /{id} - | - +-- IAddToRelationshipService - | POST /{id}/relationships/{relationship} - | - +-- ISetRelationshipService - | PATCH /{id}/relationships/{relationship} - | - +-- IRemoveFromRelationshipService - DELETE /{id}/relationships/{relationship} +```mermaid +classDiagram +direction LR +class IResourceService +class IResourceQueryService +class IGetAllService ["IGetAllService\nGET /"] +class IGetByIdService ["IGetByIdService\nGET /{id}"] +class IGetSecondaryService ["IGetSecondaryService\nGET /{id}/{relationship}"] +class IGetRelationshipService ["IGetRelationshipService\nGET /{id}/relationships/{relationship}"] +class IResourceCommandService +class ICreateService ["ICreateService\nPOST /"] +class IUpdateService ["IUpdateService\nPATCH /{id}"] +class IDeleteService ["IDeleteService\nDELETE /{id}"] +class IAddToRelationshipService ["IAddToRelationshipService\nPOST /{id}/relationships/{relationship}"] +class ISetRelationshipService ["ISetRelationshipService\nPATCH /{id}/relationships/{relationship}"] +class IRemoveFromRelationshipService ["IRemoveFromRelationshipService\nDELETE /{id}/relationships/{relationship}"] +IResourceService <|-- IResourceQueryService +IResourceQueryService<|-- IGetAllService +IResourceQueryService<|-- IGetByIdService +IResourceQueryService<|-- IGetSecondaryService +IResourceQueryService<|-- IGetRelationshipService +IResourceService <|-- IResourceCommandService +IResourceCommandService <|-- ICreateService +IResourceCommandService <|-- IUpdateService +IResourceCommandService <|-- IDeleteService +IResourceCommandService <|-- IAddToRelationshipService +IResourceCommandService <|-- ISetRelationshipService +IResourceCommandService <|-- IRemoveFromRelationshipService ``` In order to take advantage of these interfaces you first need to register the service for each implemented interface. From e49a8f4c0fbc803c72962ab420b7c74a8cc6c650 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Thu, 18 May 2023 22:14:21 +0200 Subject: [PATCH 04/41] Fix broken docs home page The new docfx template no longer produces a /styles directory, therefore it needs to be created first for the PowerShell homepage copy to succeed. https://stackoverflow.com/questions/2695504/powershell-2-copy-item-which-creates-a-folder-if-doesnt-exist Also, the allyoucan.cloud link is unreachable, which blocks loading the home page for 20 seconds. Removed the reference, not sure if it was needed. --- appveyor.yml | 1 + docs/build-dev.ps1 | 1 + docs/home/index.html | 5 ++--- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0139480fec..4b0196904d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -66,6 +66,7 @@ for: Copy-Item CNAME _site/CNAME Copy-Item home/*.html _site/ Copy-Item home/*.ico _site/ + New-Item -Force _site/styles -ItemType Directory | Out-Null Copy-Item -Recurse home/assets/* _site/styles/ CD _site git add -A 2>&1 diff --git a/docs/build-dev.ps1 b/docs/build-dev.ps1 index 6bff0e5fcb..d65826687a 100644 --- a/docs/build-dev.ps1 +++ b/docs/build-dev.ps1 @@ -45,6 +45,7 @@ VerifySuccessExitCode Copy-Item -Force home/*.html _site/ Copy-Item -Force home/*.ico _site/ +New-Item -Force _site/styles -ItemType Directory | Out-Null Copy-Item -Force -Recurse home/assets/* _site/styles/ cd _site diff --git a/docs/home/index.html b/docs/home/index.html index 7f01a30e32..a5aa7c3db3 100644 --- a/docs/home/index.html +++ b/docs/home/index.html @@ -10,7 +10,6 @@ - @@ -127,7 +126,7 @@

Customizable

Use various extensibility points to intercept and run custom code, besides just model annotations

- +
@@ -279,4 +278,4 @@

Contact us

- + From 46b50d474d6519b9e40cf2cd707569ad4746a98a Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Thu, 18 May 2023 22:51:40 +0200 Subject: [PATCH 05/41] Fix broken 'up' icon on home page --- docs/home/assets/fonts/icofont.eot | Bin 0 -> 1734 bytes docs/home/assets/fonts/icofont.svg | 11 +++++++++++ docs/home/assets/fonts/icofont.ttf | Bin 0 -> 1484 bytes docs/home/assets/fonts/icofont.woff | Bin 0 -> 968 bytes docs/home/assets/fonts/icofont.woff2 | Bin 0 -> 616 bytes docs/home/assets/icofont.min.css | 7 +++++++ docs/home/index.html | 1 + 7 files changed, 19 insertions(+) create mode 100644 docs/home/assets/fonts/icofont.eot create mode 100644 docs/home/assets/fonts/icofont.svg create mode 100644 docs/home/assets/fonts/icofont.ttf create mode 100644 docs/home/assets/fonts/icofont.woff create mode 100644 docs/home/assets/fonts/icofont.woff2 create mode 100644 docs/home/assets/icofont.min.css diff --git a/docs/home/assets/fonts/icofont.eot b/docs/home/assets/fonts/icofont.eot new file mode 100644 index 0000000000000000000000000000000000000000..47790c2f5012251940da0209d0e024a0f67cf400 GIT binary patch literal 1734 zcmd^ATWcFf7(KHq$+6rjA=gseWGQi4h$CNOlH!^YN@^1@jqwc<3S}d$E@oG|mewKm zQ=kwE^@AT;$4Lpz#Sf+RLth$52r z`a}M%{sHoGhhdlXiQIX$zrsQNNyZG_(rQ~b#~hsOs(PvR#9-27TT z(1C{_oz6K@N9;T0#>`9wGwL~kB7aQUXQ!JED6;t9z_~s>yNFWgr!9PnobhJKeweF$SH(5;mwct4 ztWvk#dB|-$KL=9=TMNAoF9$Hphr1DrW*5NsWcB%mIr7ltbNJlEXfK;*OY zK zPlg@h4U1i3`Li{0+Ss;6o-!qOtx?dP*VZUfzEn4702jpB8&6OnVFy!wEZ-wdUw{n&fWTWn%2BpJB~a(Nf3sym$c)RppupwX_`!q zjOgh!U#`T_fAqCiTYJ^B*ZQ#L_QuRmms>`geQI}rDm>i5I{OapQp3l|rl`@bQNLqE zL|vs1Sm2PHhs5|+m|tOZ84Z(_U=kzzb+x@4Up9&#@%3l_Lt2hL+#KNu7yX@Pl!U>h IwS-ac0FC1b4gdfE literal 0 HcmV?d00001 diff --git a/docs/home/assets/fonts/icofont.svg b/docs/home/assets/fonts/icofont.svg new file mode 100644 index 0000000000..685f2e87d3 --- /dev/null +++ b/docs/home/assets/fonts/icofont.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/home/assets/fonts/icofont.ttf b/docs/home/assets/fonts/icofont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9d3b07d15367e2e30c211275b586b0bdae3bffa4 GIT binary patch literal 1484 zcmd^9T}u>E7=F&oe&}wQ*e78&gjSI4t|l2KAyJATC95tJL5#bzA2PEu?T(^ebrnHg zbR|-B6a5LLyCAyk!dSY>s0%SKx~WU;IkRVB3;#i9IOja?^FHUD_kHIB0ze#(p(8am zHFMK=*0T(VYh2-=ct?qyJ*jGIQNs z8|}nfoL7q^qQm+O@mtRBqT??{KN3NF=h9-kSrf;ktv}!ram+cTlFWuy!;7-*XX|j=B}sr=eTaumaD9$d1wJc_R;U%wTDNBe<5DiZmnE@ zB881z-`393Y=NeZ%Saj`Dxzd#yny{Ce+((yfOcziVj69>>6dXDp(cMb7Ivv%GCqq7 zW++e!GJ!i-hxrwEDjXqyLE#uKA)#;_M{!R+=};?~HrNVl#LEin#7`9t5w9v7#tFPp zI6{6y;TSUbpl}@LMb~)N9d*lo+A7T3W~G#M^R(2Ku`1P)TQ>Rrb+cIFTEznI(@)k%o_3zGTsTCH zOf2SLlQZB2zB!)HQk_6CIOSmoNnVZY8u~<#v%@Ff_z%f{&Ot*Hn$Xc&EjgZTU7q)- F`2*FF!zBO! literal 0 HcmV?d00001 diff --git a/docs/home/assets/fonts/icofont.woff b/docs/home/assets/fonts/icofont.woff new file mode 100644 index 0000000000000000000000000000000000000000..8f9f5aef917a0a14ffe418c7ba158aed0826bd63 GIT binary patch literal 968 zcmXT-cXMN4WB>x@6AauSn)M8X4`QPN_ux<`1_nkBpr|zvhbVNbR{00(8v(^!fP7~l z4s*EaW00JiSO6630P?+obiwO~hp(pRRHgyhSAb#~Ae=Asm^~vkF$F002guh0Vlx%F zT>=?EK?VjU9UxyCh*j8am_sviODce39zZ_GZVvVf3=BE>$slzBKt3B7i!dm808wcE<{h?w`azaW% z!hU}8|S zX7ykI>#aLz(bzb(v2kTrCO*A_dkva2I z`6f)r6>HOzbuW|2Ieo%Q!Pe3Lg76m+TZfk$f8{Lec5}L9oqbF|dnc{o+QVz0DT@{>cdpJo?K|D$(Dxt`;@ z;lbrVHPb(EDAu*q+En(>zOlyVMhtPuB_cYK;!vBQfMhdZ_q2_`N6ZGZb5}YGPOcAS({6-D$;BE#aH`&{8@}d zQk9|R;P%XgU3t#QN0mo!)#3X&FLZ;98K59eXmU?UC|y#YEE@v8DueP$r8#b6#t{qa}9#s3SM%l~Q{atZz{ z)hxL*7XY>Ue8K-qn2p*cK%1zv$V8Y_`__X!aaHBCjBmH&Bporb@S8rdqQfrrw$VLmP}m-=@RooXQ<} zd2E@$VP%SA(i531;1p+b3zsJ@C?#VFxoCf3_U_F^6e`0B-f$VkF{3sdk|SeZL@y@u zx9kIBhZDHsVCPs$+##M^%whzbs1~Q@C&b7E)*qS~n~uSSE}apz2;v@U`+_p>Jaa-Q zNJ*9@(8VYci!r46s1R|8F@GVhElhGJHLDwM4<(8qMm=+iv?Qy0c}R3jqg(?30002& Ctp_Cl literal 0 HcmV?d00001 diff --git a/docs/home/assets/icofont.min.css b/docs/home/assets/icofont.min.css new file mode 100644 index 0000000000..58ff34474c --- /dev/null +++ b/docs/home/assets/icofont.min.css @@ -0,0 +1,7 @@ +/*! +* @package IcoFont +* @version 1.0.1 +* @author IcoFont https://icofont.com +* @copyright Copyright (c) 2015 - 2023 IcoFont +* @license - https://icofont.com/license/ +*/@font-face{font-family:IcoFont;font-weight:400;font-style:Regular;src:url(fonts/icofont.woff2) format("woff2"),url(fonts/icofont.woff) format("woff")}[class*=" icofont-"],[class^=icofont-]{font-family:IcoFont!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;white-space:nowrap;word-wrap:normal;direction:ltr;line-height:1;-webkit-font-feature-settings:"liga";-webkit-font-smoothing:antialiased}.icofont-simple-up:before{content:"\eab9"}.icofont-xs{font-size:.5em}.icofont-sm{font-size:.75em}.icofont-md{font-size:1.25em}.icofont-lg{font-size:1.5em}.icofont-1x{font-size:1em}.icofont-2x{font-size:2em}.icofont-3x{font-size:3em}.icofont-4x{font-size:4em}.icofont-5x{font-size:5em}.icofont-6x{font-size:6em}.icofont-7x{font-size:7em}.icofont-8x{font-size:8em}.icofont-9x{font-size:9em}.icofont-10x{font-size:10em}.icofont-fw{text-align:center;width:1.25em}.icofont-ul{list-style-type:none;padding-left:0;margin-left:0}.icofont-ul>li{position:relative;line-height:2em}.icofont-ul>li .icofont{display:inline-block;vertical-align:middle}.icofont-border{border:solid .08em #f1f1f1;border-radius:.1em;padding:.2em .25em .15em}.icofont-pull-left{float:left}.icofont-pull-right{float:right}.icofont.icofont-pull-left{margin-right:.3em}.icofont.icofont-pull-right{margin-left:.3em}.icofont-spin{-webkit-animation:icofont-spin 2s infinite linear;animation:icofont-spin 2s infinite linear;display:inline-block}.icofont-pulse{-webkit-animation:icofont-spin 1s infinite steps(8);animation:icofont-spin 1s infinite steps(8);display:inline-block}@-webkit-keyframes icofont-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes icofont-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.icofont-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.icofont-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.icofont-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.icofont-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.icofont-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.icofont-flip-horizontal.icofont-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}:root .icofont-flip-horizontal,:root .icofont-flip-vertical,:root .icofont-rotate-180,:root .icofont-rotate-270,:root .icofont-rotate-90{-webkit-filter:none;filter:none;display:inline-block}.icofont-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file diff --git a/docs/home/index.html b/docs/home/index.html index a5aa7c3db3..fae1d090be 100644 --- a/docs/home/index.html +++ b/docs/home/index.html @@ -14,6 +14,7 @@ +
From 99da7af1e6150b5788c34af0c7d633c142779829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogi=20Napoleon=20Wennerstr=C3=B8m?= Date: Fri, 26 May 2023 10:31:42 +0200 Subject: [PATCH 06/41] Corrected HTTP method in updating.md --- docs/usage/writing/updating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/writing/updating.md b/docs/usage/writing/updating.md index 01d0740cba..ea27e1a220 100644 --- a/docs/usage/writing/updating.md +++ b/docs/usage/writing/updating.md @@ -5,7 +5,7 @@ To modify the attributes of a single resource, send a PATCH request. The next example changes the article caption: ```http -POST /articles HTTP/1.1 +PATCH /articles HTTP/1.1 { "data": { From b3b6262e1dd125a432a29fe87664a8afc68e54f2 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Tue, 23 May 2023 23:02:38 +0200 Subject: [PATCH 07/41] Repro for https://youtrack.jetbrains.com/issue/RSRP-491451 --- .../Controllers/EmployeesController.cs | 5 ----- .../ControllerActionResults/ToothbrushesController.cs | 5 ----- .../IntegrationTests/CustomRoutes/CiviliansController.cs | 5 ----- .../IntegrationTests/CustomRoutes/TownsController.cs | 5 ----- .../IntegrationTests/HostingInIIS/PaintingsController.cs | 5 ----- .../IntegrationTests/MultiTenancy/WebProductsController.cs | 5 ----- .../IntegrationTests/MultiTenancy/WebShopsController.cs | 5 ----- .../RestrictedControllers/PillowsController.cs | 5 ----- .../RestrictedControllers/SofasController.cs | 5 ----- 9 files changed, 45 deletions(-) diff --git a/src/Examples/DatabasePerTenantExample/Controllers/EmployeesController.cs b/src/Examples/DatabasePerTenantExample/Controllers/EmployeesController.cs index 5e17afab9b..f9d5595123 100644 --- a/src/Examples/DatabasePerTenantExample/Controllers/EmployeesController.cs +++ b/src/Examples/DatabasePerTenantExample/Controllers/EmployeesController.cs @@ -3,11 +3,6 @@ namespace DatabasePerTenantExample.Controllers; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class EmployeesController -{ -} - [DisableRoutingConvention] [Route("api/{tenantName}/employees")] partial class EmployeesController diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ToothbrushesController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ToothbrushesController.cs index 2170d113ce..5d8793b453 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ToothbrushesController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/ControllerActionResults/ToothbrushesController.cs @@ -4,11 +4,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.ControllerActionResults; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class ToothbrushesController -{ -} - partial class ToothbrushesController { internal const int EmptyActionResultId = 11111111; diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CiviliansController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CiviliansController.cs index 313a8e8849..5d4da838c9 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CiviliansController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/CiviliansController.cs @@ -3,11 +3,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.CustomRoutes; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class CiviliansController -{ -} - [ApiController] [DisableRoutingConvention] [Route("world-civilians")] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/TownsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/TownsController.cs index e3fab1ff3c..f99f3aa225 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/TownsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/CustomRoutes/TownsController.cs @@ -8,11 +8,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.CustomRoutes; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class TownsController -{ -} - [DisableRoutingConvention] [Route("world-api/civilization/popular/towns")] partial class TownsController diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/PaintingsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/PaintingsController.cs index bf7b915f03..dc4c27ca54 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/PaintingsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/HostingInIIS/PaintingsController.cs @@ -3,11 +3,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.HostingInIIS; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class PaintingsController -{ -} - [DisableRoutingConvention] [Route("custom/path/to/paintings-of-the-world")] partial class PaintingsController diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebProductsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebProductsController.cs index c11db3422e..bdc7068a3d 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebProductsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebProductsController.cs @@ -3,11 +3,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.MultiTenancy; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class WebProductsController -{ -} - [DisableRoutingConvention] [Route("{countryCode}/products")] partial class WebProductsController diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebShopsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebShopsController.cs index b300e0095d..ee31954740 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebShopsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/MultiTenancy/WebShopsController.cs @@ -3,11 +3,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.MultiTenancy; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class WebShopsController -{ -} - [DisableRoutingConvention] [Route("{countryCode}/shops")] partial class WebShopsController diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/PillowsController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/PillowsController.cs index f50cae1908..e260788905 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/PillowsController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/PillowsController.cs @@ -2,11 +2,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.RestrictedControllers; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class PillowsController -{ -} - [DisableQueryString("skipCache")] partial class PillowsController { diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/SofasController.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/SofasController.cs index 8ec503ce22..d6d2d66fa8 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/SofasController.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/SofasController.cs @@ -3,11 +3,6 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.RestrictedControllers; -// Workaround for https://youtrack.jetbrains.com/issue/RSRP-487028 -public partial class SofasController -{ -} - [DisableQueryString(JsonApiQueryStringParameters.Sort | JsonApiQueryStringParameters.Page)] partial class SofasController { From 3ebe52cb7bcad5c73b0a105bd462ee5b9398863d Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 14 Jun 2023 15:23:37 +0200 Subject: [PATCH 08/41] Add missing controller annotations in tests --- test/DiscoveryTests/PrivateResource.cs | 2 ++ .../IntegrationTests/EagerLoading/City.cs | 1 + .../IntegrationTests/IdObfuscation/BankAccount.cs | 2 ++ .../IntegrationTests/IdObfuscation/DebitCard.cs | 2 ++ .../IntegrationTests/NamingConventions/DivingBoard.cs | 2 ++ .../IntegrationTests/NamingConventions/SwimmingPool.cs | 2 ++ .../IntegrationTests/NamingConventions/WaterSlide.cs | 2 ++ .../IntegrationTests/QueryStrings/AccountPreferences.cs | 1 + .../IntegrationTests/QueryStrings/Appointment.cs | 1 + .../IntegrationTests/QueryStrings/Label.cs | 1 + .../IntegrationTests/QueryStrings/LoginAttempt.cs | 1 + .../IntegrationTests/RestrictedControllers/Room.cs | 1 + 12 files changed, 18 insertions(+) diff --git a/test/DiscoveryTests/PrivateResource.cs b/test/DiscoveryTests/PrivateResource.cs index ed6dc23204..facbfb6c35 100644 --- a/test/DiscoveryTests/PrivateResource.cs +++ b/test/DiscoveryTests/PrivateResource.cs @@ -1,9 +1,11 @@ using JetBrains.Annotations; using JsonApiDotNetCore.Resources; +using JsonApiDotNetCore.Resources.Annotations; namespace DiscoveryTests; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource] public sealed class PrivateResource : Identifiable { } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/City.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/City.cs index fea280724b..66e8dacb2c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/City.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/EagerLoading/City.cs @@ -5,6 +5,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.EagerLoading; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.EagerLoading")] public sealed class City : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/BankAccount.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/BankAccount.cs index 911054f291..663b2a3bd6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/BankAccount.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/BankAccount.cs @@ -1,9 +1,11 @@ using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.IdObfuscation; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.None)] public sealed class BankAccount : ObfuscatedIdentifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/DebitCard.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/DebitCard.cs index 323d1bd1e3..99f0154147 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/DebitCard.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/IdObfuscation/DebitCard.cs @@ -1,9 +1,11 @@ using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.IdObfuscation; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.None)] public sealed class DebitCard : ObfuscatedIdentifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/DivingBoard.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/DivingBoard.cs index 4cb4581291..b1df54874f 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/DivingBoard.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/DivingBoard.cs @@ -1,11 +1,13 @@ using System.ComponentModel.DataAnnotations; using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.NamingConventions; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.None)] public sealed class DivingBoard : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/SwimmingPool.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/SwimmingPool.cs index 2b715edc7d..ce786ff839 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/SwimmingPool.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/SwimmingPool.cs @@ -1,10 +1,12 @@ using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.NamingConventions; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.None)] public sealed class SwimmingPool : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/WaterSlide.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/WaterSlide.cs index 95bda04456..9dbd17662e 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/WaterSlide.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NamingConventions/WaterSlide.cs @@ -1,10 +1,12 @@ using JetBrains.Annotations; +using JsonApiDotNetCore.Controllers; using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Resources.Annotations; namespace JsonApiDotNetCoreTests.IntegrationTests.NamingConventions; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(GenerateControllerEndpoints = JsonApiEndpoints.None)] public sealed class WaterSlide : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/AccountPreferences.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/AccountPreferences.cs index 20c95ea769..5b00f1bb0c 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/AccountPreferences.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/AccountPreferences.cs @@ -5,6 +5,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.QueryStrings")] public sealed class AccountPreferences : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Appointment.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Appointment.cs index 2f90ed2615..2805745644 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Appointment.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Appointment.cs @@ -5,6 +5,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.QueryStrings")] public sealed class Appointment : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Label.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Label.cs index acd1fa446c..07804aeac6 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Label.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/Label.cs @@ -5,6 +5,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.QueryStrings")] public sealed class Label : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/LoginAttempt.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/LoginAttempt.cs index 73557d7fcf..007182781a 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/LoginAttempt.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/QueryStrings/LoginAttempt.cs @@ -5,6 +5,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.QueryStrings; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.QueryStrings")] public sealed class LoginAttempt : Identifiable { [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/Room.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/Room.cs index 2860b6d344..8b09419c2b 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/Room.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/RestrictedControllers/Room.cs @@ -5,6 +5,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.RestrictedControllers; [UsedImplicitly(ImplicitUseTargetFlags.Members)] +[Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.RestrictedControllers")] public sealed class Room : Identifiable { [Attr] From c0eb10863d44c498d8cebeadb13e50eb1350d877 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 14 Jun 2023 17:06:36 +0200 Subject: [PATCH 09/41] Fix build warning ASP0019, produced by ASP.NET Core 8 --- src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs b/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs index 8f77a2ff5c..27923f6f62 100644 --- a/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs +++ b/src/JsonApiDotNetCore/Serialization/Response/JsonApiWriter.cs @@ -137,7 +137,7 @@ private bool SetETagResponseHeader(HttpRequest request, HttpResponse response, s string url = request.GetEncodedUrl(); EntityTagHeaderValue responseETag = _eTagGenerator.Generate(url, responseContent); - response.Headers.Add(HeaderNames.ETag, responseETag.ToString()); + response.Headers.Append(HeaderNames.ETag, responseETag.ToString()); return RequestContainsMatchingETag(request.Headers, responseETag); } From 6d8e44e033ef1a63338783e4f812201287b224f7 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Wed, 14 Jun 2023 23:05:12 +0200 Subject: [PATCH 10/41] Fix Resharper warnings from upcoming new version --- .../SourceCodeWriter.cs | 4 ++-- .../AtomicOperations/MusicTrack.cs | 2 +- .../NonJsonApiControllerTests.cs | 22 +++++++++---------- .../ControllerGenerationTests.cs | 2 +- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs b/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs index 648906e901..0ce666e342 100644 --- a/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs +++ b/src/JsonApiDotNetCore.SourceGenerators/SourceCodeWriter.cs @@ -98,7 +98,7 @@ private void WriteNullableEnable() private void WriteNamespaceImports(INamedTypeSymbol loggerFactoryInterface, INamedTypeSymbol resourceType, string? controllerNamespace) { - _sourceBuilder.AppendLine($@"using {loggerFactoryInterface.ContainingNamespace};"); + _sourceBuilder.AppendLine($"using {loggerFactoryInterface.ContainingNamespace};"); _sourceBuilder.AppendLine("using JsonApiDotNetCore.Configuration;"); _sourceBuilder.AppendLine("using JsonApiDotNetCore.Controllers;"); @@ -123,7 +123,7 @@ private void WriteOpenClassDeclaration(string controllerName, JsonApiEndpointsCo string baseClassName = GetControllerBaseClassName(endpointsToGenerate); WriteIndent(); - _sourceBuilder.AppendLine($@"public sealed partial class {controllerName} : {baseClassName}<{resourceType.Name}, {idType}>"); + _sourceBuilder.AppendLine($"public sealed partial class {controllerName} : {baseClassName}<{resourceType.Name}, {idType}>"); WriteOpenCurly(); } diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/MusicTrack.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/MusicTrack.cs index 52ed0ae98b..0abf7385ee 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/MusicTrack.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/MusicTrack.cs @@ -9,7 +9,7 @@ namespace JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations; [Resource(ControllerNamespace = "JsonApiDotNetCoreTests.IntegrationTests.AtomicOperations")] public sealed class MusicTrack : Identifiable { - [RegularExpression(@"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$")] + [RegularExpression("(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$")] public override Guid Id { get; set; } [Attr] diff --git a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs index 88e9ecfd82..3c4a6a6bae 100644 --- a/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs +++ b/test/JsonApiDotNetCoreTests/IntegrationTests/NonJsonApiControllers/NonJsonApiControllerTests.cs @@ -41,14 +41,13 @@ public async Task Get_skips_middleware_and_formatters() public async Task Post_skips_middleware_and_formatters() { // Arrange - using var request = new HttpRequestMessage(HttpMethod.Post, "/NonJsonApi") + using var request = new HttpRequestMessage(HttpMethod.Post, "/NonJsonApi"); + + request.Content = new StringContent("Jack") { - Content = new StringContent("Jack") + Headers = { - Headers = - { - ContentType = new MediaTypeHeaderValue("text/plain") - } + ContentType = new MediaTypeHeaderValue("text/plain") } }; @@ -90,14 +89,13 @@ public async Task Post_skips_error_handler() public async Task Put_skips_middleware_and_formatters() { // Arrange - using var request = new HttpRequestMessage(HttpMethod.Put, "/NonJsonApi") + using var request = new HttpRequestMessage(HttpMethod.Put, "/NonJsonApi"); + + request.Content = new StringContent("\"Jane\"") { - Content = new StringContent("\"Jane\"") + Headers = { - Headers = - { - ContentType = new MediaTypeHeaderValue("application/json") - } + ContentType = new MediaTypeHeaderValue("application/json") } }; diff --git a/test/SourceGeneratorTests/ControllerGenerationTests.cs b/test/SourceGeneratorTests/ControllerGenerationTests.cs index 629c5d49b8..44c63ffe54 100644 --- a/test/SourceGeneratorTests/ControllerGenerationTests.cs +++ b/test/SourceGeneratorTests/ControllerGenerationTests.cs @@ -538,7 +538,7 @@ public sealed class Item : Identifiable GeneratorDriverRunResult runResult = driver.GetRunResult(); runResult.Should().NotHaveDiagnostics(); - runResult.Should().HaveProducedSourceCodeContaining(@"#nullable enable"); + runResult.Should().HaveProducedSourceCodeContaining("#nullable enable"); } [Fact] From 336b7254430490c4f3c704c7aef34c873f2c8b92 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sun, 16 Jul 2023 13:15:15 +0200 Subject: [PATCH 11/41] Do not execute unneeded SQL query in 1-to-1 relationship update, which fails on EF Core 8 (details at https://github.com/dotnet/efcore/issues/31271) --- .../Repositories/EntityFrameworkCoreRepository.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs index 66abfafbe0..6b36d9d84c 100644 --- a/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs +++ b/src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs @@ -619,7 +619,18 @@ protected async Task UpdateRelationshipAsync(RelationshipAttribute relationship, private bool RequireLoadOfInverseRelationship(RelationshipAttribute relationship, [NotNullWhen(true)] object? trackedValueToAssign) { // See https://github.com/json-api-dotnet/JsonApiDotNetCore/issues/502. - return trackedValueToAssign != null && relationship is HasOneAttribute { IsOneToOne: true }; + if (trackedValueToAssign != null && relationship is HasOneAttribute { IsOneToOne: true }) + { + IEntityType? leftEntityType = _dbContext.Model.FindEntityType(relationship.LeftType.ClrType); + INavigation? navigation = leftEntityType?.FindNavigation(relationship.Property.Name); + + if (navigation != null && navigation.ForeignKey.DeclaringEntityType.ClrType == relationship.LeftType.ClrType) + { + return true; + } + } + + return false; } protected virtual async Task SaveChangesAsync(CancellationToken cancellationToken) From c07b0c2dc97550a5288022c7b966ec4c3944bb83 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Jul 2023 14:12:29 +0200 Subject: [PATCH 12/41] Reformat .html file with 2 spaces as indent --- .editorconfig | 2 +- docs/home/index.html | 365 +++++++++++++++++++++---------------------- 2 files changed, 181 insertions(+), 186 deletions(-) diff --git a/.editorconfig b/.editorconfig index 86cbbc3700..5a036d1797 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,7 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.{config,csproj,css,js,json,props,ruleset,xslt}] +[*.{config,csproj,css,js,json,props,ruleset,xslt,html}] indent_size = 2 [*.{cs}] diff --git a/docs/home/index.html b/docs/home/index.html index fae1d090be..8b923811f9 100644 --- a/docs/home/index.html +++ b/docs/home/index.html @@ -1,147 +1,147 @@ - - - - JsonApiDotNetCore documentation - - - - - - - - - - - - - -
-
+ + + + JsonApiDotNetCore documentation + + + + + + + + + + + + + +
+
+
+
+

JsonApiDotNetCore

+

A framework for building JSON:API compliant REST APIs using .NET Core and Entity Framework Core. Includes support for Atomic Operations.

+ Read more + Getting started + Contribute on GitHub +
+
+ project logo +
+
+
+
+
+
+
+
+
+ people working at desk +
+
+

Objectives

+

+ The goal of this library is to simplify the development of APIs that leverage the full range of features provided by the JSON:API specification. + You just need to focus on defining the resources and implementing your custom business logic. +

-
-

JsonApiDotNetCore

-

A framework for building JSON:API compliant REST APIs using .NET Core and Entity Framework Core. Includes support for Atomic Operations.

- Read more - Getting started - Contribute on GitHub -
-
- project logo -
+
+ +

Eliminate boilerplate

+

We strive to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination.

+
+
+ +

Extensibility

+

This library has been designed around dependency injection, making extensibility incredibly easy.

+
-
-
-
-
-
-
-
- people working at desk -
-
-

Objectives

-

- The goal of this library is to simplify the development of APIs that leverage the full range of features provided by the JSON:API specification. - You just need to focus on defining the resources and implementing your custom business logic. -

-
-
- -

Eliminate boilerplate

-

We strive to eliminate as much boilerplate as possible by offering out-of-the-box features such as sorting, filtering and pagination.

-
-
- -

Extensibility

-

This library has been designed around dependency injection, making extensibility incredibly easy.

-
-
-
-
+
+
+ +
+
+
+
+

Features

+

The following features are supported, from HTTP all the way down to the database

+
+
+
+
+
+

Filtering

+

Perform compound filtering using the filter query string parameter

-
-
-
-
-

Features

-

The following features are supported, from HTTP all the way down to the database

-
-
-
-
-
-

Filtering

-

Perform compound filtering using the filter query string parameter

-
-
-
-
-
-

Sorting

-

Order resources on one or multiple attributes using the sort query string parameter

-
-
- -
-
-
-

Sparse fieldset selection

-

Get only the data that you need using the fields query string parameter

-
-
-
-
-
-
-
-

Relationship inclusion

-

Side-load related resources of nested relationships using the include query string parameter

-
-
-
-
-
-

Security

-

Configure permissions, such as view/create/change/sort/filter of attributes and relationships

-
-
-
-
-
-

Validation

-

Validate incoming requests using built-in ASP.NET Core ModelState validation, which works seamlessly with partial updates

-
-
-
-
-
-

Customizable

-

Use various extensibility points to intercept and run custom code, besides just model annotations

-
-
-
-
-
-
-
-
-

Example usage

-

Expose resources with attributes and relationships

+
+
+
+
+

Sorting

+

Order resources on one or multiple attributes using the sort query string parameter

-
-
-
-
-

Resource

-
+          
+ +
+
+
+

Sparse fieldset selection

+

Get only the data that you need using the fields query string parameter

+
+
+
+
+
+
+
+

Relationship inclusion

+

Side-load related resources of nested relationships using the include query string parameter

+
+
+
+
+
+

Security

+

Configure permissions, such as view/create/change/sort/filter of attributes and relationships

+
+
+
+
+
+

Validation

+

Validate incoming requests using built-in ASP.NET Core ModelState validation, which works seamlessly with partial updates

+
+
+
+
+
+

Customizable

+

Use various extensibility points to intercept and run custom code, besides just model annotations

+
+
+
+
+
+
+
+
+

Example usage

+

Expose resources with attributes and relationships

+
+
+
+
+
+

Resource

+
 #nullable enable
 
 public class Article : Identifiable<long>
@@ -172,31 +172,26 @@ 

Resource

[HasMany] public ICollection<Tag> Tags { get; set; } = new HashSet<Tag>(); }
-
-
-
+
-
-
-
-
-

Request

-
-
-GET /articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields[articles]=title,summary&include=author HTTP/1.1
-
-                     
-
-
+
+
+
+
+
+
+

Request

+
GET /articles?filter=contains(summary,'web')&sort=-lastModifiedAt&fields[articles]=title,summary&include=author HTTP/1.1
-
-
-
-
-

Response

-
-
-{
+          
+
+
+
+
+
+

Response

+
+{
   "meta": {
     "totalResources": 1
   },
@@ -252,31 +247,31 @@ 

Response

] }
-
-
-
+
-
-
-
- + +
+
+
- - - - - - - - - + + + + + + + + + + + + From 392d724d5140d24de93afe4184c1a20685fd9a37 Mon Sep 17 00:00:00 2001 From: Bart Koelman <10324372+bkoelman@users.noreply.github.com> Date: Sat, 22 Jul 2023 14:25:05 +0200 Subject: [PATCH 13/41] Add sponsors to docs landing page and root readme --- README.md | 5 +++++ docs/home/assets/home.css | 35 ++++++++++++++++++++++++++++------- docs/home/assets/home.js | 11 ++++++++--- docs/home/index.html | 23 +++++++++++++++++++++++ 4 files changed, 64 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 26432ee909..b3ffb5db90 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,8 @@ Alternatively, to build and validate the code, run all tests, generate code cove ```bash pwsh Build.ps1 ``` + +## Sponsors + +JetBrains Logo   +Araxis Logo diff --git a/docs/home/assets/home.css b/docs/home/assets/home.css index bfd6f96e06..273efe261b 100644 --- a/docs/home/assets/home.css +++ b/docs/home/assets/home.css @@ -95,7 +95,6 @@ h1, h2, h3, h4, h5, h6, .font-primary { margin-top: 72px; } - /*-------------------------------------------------------------- # Hero Section --------------------------------------------------------------*/ @@ -300,12 +299,6 @@ section { .breadcrumbs ol li { display: inline-block; } - - -} - -div[feature]:hover { - cursor: pointer; } /*-------------------------------------------------------------- @@ -401,6 +394,34 @@ div[feature]:hover { margin-bottom: 0; } +div[feature]:hover { + cursor: pointer; +} + +/*-------------------------------------------------------------- +# Sponsors +--------------------------------------------------------------*/ +.sponsors .icon-box { + padding: 30px; + position: relative; + overflow: hidden; + margin: 0 0 40px 0; + background: #fff; + box-shadow: 0 10px 29px 0 rgba(68, 88, 144, 0.1); + transition: all 0.3s ease-in-out; + border-radius: 15px; + text-align: center; + border-bottom: 3px solid #fff; +} + +.sponsors .icon-box:hover { + transform: translateY(-5px); + border-color: #ef7f4d; +} + +div[sponsor]:hover { + cursor: pointer; +} /*-------------------------------------------------------------- # Footer diff --git a/docs/home/assets/home.js b/docs/home/assets/home.js index cb8ac539bd..ed6571bf23 100644 --- a/docs/home/assets/home.js +++ b/docs/home/assets/home.js @@ -38,7 +38,6 @@ } }); - // Feature panels linking $('div[feature]#filter').on('click', () => navigateTo('usage/reading/filtering.html')); $('div[feature]#sort').on('click', () => navigateTo('usage/reading/sorting.html')); @@ -49,13 +48,19 @@ $('div[feature]#validation').on('click', () => navigateTo('usage/options.html#enable-modelstate-validation')); $('div[feature]#customizable').on('click', () => navigateTo('usage/extensibility/resource-definitions.html')); - const navigateTo = (url) => { - if (!window.getSelection().toString()){ + if (!window.getSelection().toString()) { window.location = url; } } + // Sponsor panels linking + $('div[sponsor]#jetbrains').on('click', () => navigateExternalTo('https://jb.gg/OpenSourceSupport')); + $('div[sponsor]#araxis').on('click', () => navigateExternalTo('https://www.araxis.com/buy/open-source')); + + const navigateExternalTo = (url) => { + window.open(url, "_blank"); + } hljs.initHighlightingOnLoad() diff --git a/docs/home/index.html b/docs/home/index.html index 8b923811f9..f4990be2ae 100644 --- a/docs/home/index.html +++ b/docs/home/index.html @@ -253,6 +253,29 @@

Response

+
+
+
+

Sponsors

+
+
+
+
+
+ JetBrains Logo +
+
+
+
+
+
+ Araxis Logo +
+
+
+
+
+