Skip to content

Commit 47f5d8f

Browse files
sebastienrosKahbaziJamesNK
authored
Output caching middleware (#41037)
* Create output caching middleware * Fix MVC attribute * Update src/Middleware/OutputCaching/src/Policies/EnableCachingPolicy.cs Co-authored-by: Kahbazi <[email protected]> * Update src/Middleware/OutputCaching/src/DispatcherExtensions.cs Co-authored-by: Kahbazi <[email protected]> * Update src/Middleware/OutputCaching/src/Policies/PredicatePolicy.cs Co-authored-by: Kahbazi <[email protected]> * Update src/Middleware/OutputCaching/src/Policies/ExpirationPolicy.cs Co-authored-by: Kahbazi <[email protected]> * Fix mention of response cache * Update src/Middleware/OutputCaching/src/OutputCachingPolicyProvider.cs Co-authored-by: Kahbazi <[email protected]> * Use IReadOnlyList in IPoliciesMetadata * Add XML documentation * Missing changes * Remove unused file * PR feedback * Fix build * Add Path sample * Fix build * Update public api * Fix typos [skip ci] * Update sample [skip ci] * Fix build * API cleaning and test project * Update src/Middleware/OutputCaching.Abstractions/src/Microsoft.AspNetCore.OutputCaching.Abstractions.csproj Co-authored-by: James Newton-King <[email protected]> * Update src/Middleware/OutputCaching/src/Microsoft.AspNetCore.OutputCaching.csproj Co-authored-by: James Newton-King <[email protected]> * Update TrimmableProjects * Fix solution * Improve ThrowIfNull usage * API review feedback * Add more tests * Update API * Clean up api * Update unit tests * Remove CachedResponseHeaders from public API * Fix unshipped file * API review feedback * Fix unit tests * Feedback * Refactor resolved policies * Clean sample * Provide HttpContext in VaryByValue * Reduce public API * Apply API review changes * Add more tests * Add more tests * Apply PR feedback * PR feedback * PR feedback * Brennan's * Update submodule (#42357) Co-authored-by: Kahbazi <[email protected]> Co-authored-by: James Newton-King <[email protected]>
1 parent 8ea458d commit 47f5d8f

File tree

93 files changed

+7588
-11
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+7588
-11
lines changed

AspNetCore.sln

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
16541654
EndProject
16551655
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.SdkAnalyzers.Tests", "src\Tools\SDK-Analyzers\Components\test\Microsoft.AspNetCore.Components.SdkAnalyzers.Tests.csproj", "{DC349A25-0DBF-4468-99E1-B95C22D3A7EF}"
16561656
EndProject
1657+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OutputCaching", "OutputCaching", "{AA5ABFBC-177C-421E-B743-005E0FD1248B}"
1658+
EndProject
1659+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.OutputCaching", "src\Middleware\OutputCaching\src\Microsoft.AspNetCore.OutputCaching.csproj", "{5D5A3B60-A014-447C-9126-B1FA6C821C8D}"
1660+
EndProject
1661+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{B5AC1D8B-9D43-4261-AE0F-6B7574656F2C}"
1662+
EndProject
1663+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OutputCachingSample", "src\Middleware\OutputCaching\samples\OutputCachingSample\OutputCachingSample.csproj", "{C3FFA4E4-0E7E-4866-A15F-034245BFD800}"
1664+
EndProject
16571665
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RequestDecompression", "RequestDecompression", "{5465F96F-33D5-454E-9C40-494E58AEEE5D}"
16581666
EndProject
16591667
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.RequestDecompression.Tests", "src\Middleware\RequestDecompression\test\Microsoft.AspNetCore.RequestDecompression.Tests.csproj", "{97996D39-7722-4AFC-A41A-AD61CA7A413D}"
@@ -1700,6 +1708,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildAfterTargetingPack", "
17001708
EndProject
17011709
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildAfterTargetingPack", "src\BuildAfterTargetingPack\BuildAfterTargetingPack.csproj", "{8FED7E65-A7DD-4F13-8980-BF03E77B6C85}"
17021710
EndProject
1711+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.OutputCaching.Tests", "src\Middleware\OutputCaching\test\Microsoft.AspNetCore.OutputCaching.Tests.csproj", "{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}"
1712+
EndProject
17031713
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResultsOfTGenerator", "src\Http\Http.Results\tools\ResultsOfTGenerator\ResultsOfTGenerator.csproj", "{9716D0D0-2251-44DD-8596-67D253EEF41C}"
17041714
EndProject
17051715
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OpenApi", "OpenApi", "{2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}"
@@ -9991,6 +10001,38 @@ Global
999110001
{DC349A25-0DBF-4468-99E1-B95C22D3A7EF}.Release|x64.Build.0 = Release|Any CPU
999210002
{DC349A25-0DBF-4468-99E1-B95C22D3A7EF}.Release|x86.ActiveCfg = Release|Any CPU
999310003
{DC349A25-0DBF-4468-99E1-B95C22D3A7EF}.Release|x86.Build.0 = Release|Any CPU
10004+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
10005+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
10006+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|arm64.ActiveCfg = Debug|Any CPU
10007+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|arm64.Build.0 = Debug|Any CPU
10008+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|x64.ActiveCfg = Debug|Any CPU
10009+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|x64.Build.0 = Debug|Any CPU
10010+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|x86.ActiveCfg = Debug|Any CPU
10011+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Debug|x86.Build.0 = Debug|Any CPU
10012+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
10013+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|Any CPU.Build.0 = Release|Any CPU
10014+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|arm64.ActiveCfg = Release|Any CPU
10015+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|arm64.Build.0 = Release|Any CPU
10016+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|x64.ActiveCfg = Release|Any CPU
10017+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|x64.Build.0 = Release|Any CPU
10018+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|x86.ActiveCfg = Release|Any CPU
10019+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D}.Release|x86.Build.0 = Release|Any CPU
10020+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
10021+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|Any CPU.Build.0 = Debug|Any CPU
10022+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|arm64.ActiveCfg = Debug|Any CPU
10023+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|arm64.Build.0 = Debug|Any CPU
10024+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|x64.ActiveCfg = Debug|Any CPU
10025+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|x64.Build.0 = Debug|Any CPU
10026+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|x86.ActiveCfg = Debug|Any CPU
10027+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Debug|x86.Build.0 = Debug|Any CPU
10028+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|Any CPU.ActiveCfg = Release|Any CPU
10029+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|Any CPU.Build.0 = Release|Any CPU
10030+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|arm64.ActiveCfg = Release|Any CPU
10031+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|arm64.Build.0 = Release|Any CPU
10032+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|x64.ActiveCfg = Release|Any CPU
10033+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|x64.Build.0 = Release|Any CPU
10034+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|x86.ActiveCfg = Release|Any CPU
10035+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800}.Release|x86.Build.0 = Release|Any CPU
999410036
{97996D39-7722-4AFC-A41A-AD61CA7A413D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
999510037
{97996D39-7722-4AFC-A41A-AD61CA7A413D}.Debug|Any CPU.Build.0 = Debug|Any CPU
999610038
{97996D39-7722-4AFC-A41A-AD61CA7A413D}.Debug|arm64.ActiveCfg = Debug|Any CPU
@@ -10215,6 +10257,22 @@ Global
1021510257
{8FED7E65-A7DD-4F13-8980-BF03E77B6C85}.Release|x64.Build.0 = Release|Any CPU
1021610258
{8FED7E65-A7DD-4F13-8980-BF03E77B6C85}.Release|x86.ActiveCfg = Release|Any CPU
1021710259
{8FED7E65-A7DD-4F13-8980-BF03E77B6C85}.Release|x86.Build.0 = Release|Any CPU
10260+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
10261+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
10262+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|arm64.ActiveCfg = Debug|Any CPU
10263+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|arm64.Build.0 = Debug|Any CPU
10264+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|x64.ActiveCfg = Debug|Any CPU
10265+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|x64.Build.0 = Debug|Any CPU
10266+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|x86.ActiveCfg = Debug|Any CPU
10267+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Debug|x86.Build.0 = Debug|Any CPU
10268+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
10269+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|Any CPU.Build.0 = Release|Any CPU
10270+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|arm64.ActiveCfg = Release|Any CPU
10271+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|arm64.Build.0 = Release|Any CPU
10272+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|x64.ActiveCfg = Release|Any CPU
10273+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|x64.Build.0 = Release|Any CPU
10274+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|x86.ActiveCfg = Release|Any CPU
10275+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7}.Release|x86.Build.0 = Release|Any CPU
1021810276
{9716D0D0-2251-44DD-8596-67D253EEF41C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1021910277
{9716D0D0-2251-44DD-8596-67D253EEF41C}.Debug|Any CPU.Build.0 = Debug|Any CPU
1022010278
{9716D0D0-2251-44DD-8596-67D253EEF41C}.Debug|arm64.ActiveCfg = Debug|Any CPU
@@ -11242,6 +11300,10 @@ Global
1124211300
{CC45FA2D-128B-485D-BA6D-DFD9735CB3C3} = {6C06163A-80E9-49C1-817C-B391852BA563}
1124311301
{825BCF97-67A9-4834-B3A8-C3DC97A90E41} = {CC45FA2D-128B-485D-BA6D-DFD9735CB3C3}
1124411302
{DC349A25-0DBF-4468-99E1-B95C22D3A7EF} = {CC45FA2D-128B-485D-BA6D-DFD9735CB3C3}
11303+
{AA5ABFBC-177C-421E-B743-005E0FD1248B} = {E5963C9F-20A6-4385-B364-814D2581FADF}
11304+
{5D5A3B60-A014-447C-9126-B1FA6C821C8D} = {AA5ABFBC-177C-421E-B743-005E0FD1248B}
11305+
{B5AC1D8B-9D43-4261-AE0F-6B7574656F2C} = {AA5ABFBC-177C-421E-B743-005E0FD1248B}
11306+
{C3FFA4E4-0E7E-4866-A15F-034245BFD800} = {B5AC1D8B-9D43-4261-AE0F-6B7574656F2C}
1124511307
{5465F96F-33D5-454E-9C40-494E58AEEE5D} = {E5963C9F-20A6-4385-B364-814D2581FADF}
1124611308
{97996D39-7722-4AFC-A41A-AD61CA7A413D} = {5465F96F-33D5-454E-9C40-494E58AEEE5D}
1124711309
{37144E52-611B-40E8-807C-2821F5A814CB} = {5465F96F-33D5-454E-9C40-494E58AEEE5D}
@@ -11265,6 +11327,7 @@ Global
1126511327
{B7DAA48B-8E5E-4A5D-9FEB-E6D49AE76A04} = {41BB7BA4-AC08-4E9A-83EA-6D587A5B951C}
1126611328
{489020F2-80D9-4468-A5D3-07E785837A5D} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
1126711329
{8FED7E65-A7DD-4F13-8980-BF03E77B6C85} = {489020F2-80D9-4468-A5D3-07E785837A5D}
11330+
{046F43BC-BEE4-48B7-8C09-ED0A1054A2D7} = {AA5ABFBC-177C-421E-B743-005E0FD1248B}
1126811331
{9716D0D0-2251-44DD-8596-67D253EEF41C} = {323C3EB6-1D15-4B3D-918D-699D7F64DED9}
1126911332
{2299CCD8-8F9C-4F2B-A633-9BF4DA81022B} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
1127011333
{3AEFB466-6310-4F3F-923F-9154224E3629} = {2299CCD8-8F9C-4F2B-A633-9BF4DA81022B}

eng/ProjectReferences.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization.Routing" ProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\src\Microsoft.AspNetCore.Localization.Routing.csproj" />
9090
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization" ProjectPath="$(RepoRoot)src\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj" />
9191
<ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
92+
<ProjectReferenceProvider Include="Microsoft.AspNetCore.OutputCaching" ProjectPath="$(RepoRoot)src\Middleware\OutputCaching\src\Microsoft.AspNetCore.OutputCaching.csproj" />
9293
<ProjectReferenceProvider Include="Microsoft.AspNetCore.RateLimiting" ProjectPath="$(RepoRoot)src\Middleware\RateLimiting\src\Microsoft.AspNetCore.RateLimiting.csproj" />
9394
<ProjectReferenceProvider Include="Microsoft.AspNetCore.RequestDecompression" ProjectPath="$(RepoRoot)src\Middleware\RequestDecompression\src\Microsoft.AspNetCore.RequestDecompression.csproj" />
9495
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching.Abstractions\src\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj" />

eng/SharedFramework.Local.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<AspNetCoreAppReference Include="Microsoft.AspNetCore.HttpsPolicy" />
7878
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Localization.Routing" />
7979
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Localization" />
80+
<AspNetCoreAppReference Include="Microsoft.AspNetCore.OutputCaching" />
8081
<AspNetCoreAppReference Include="Microsoft.AspNetCore.RequestDecompression" />
8182
<AspNetCoreAppReference Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" />
8283
<AspNetCoreAppReference Include="Microsoft.AspNetCore.ResponseCaching" />

eng/TrimmableProjects.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<TrimmableProject Include="Microsoft.AspNetCore.HttpsPolicy" />
6767
<TrimmableProject Include="Microsoft.AspNetCore.Localization.Routing" />
6868
<TrimmableProject Include="Microsoft.AspNetCore.Localization" />
69+
<TrimmableProject Include="Microsoft.AspNetCore.OutputCaching" />
6970
<TrimmableProject Include="Microsoft.AspNetCore.RateLimiting" />
7071
<TrimmableProject Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" />
7172
<TrimmableProject Include="Microsoft.AspNetCore.ResponseCaching" />

src/Framework/Framework.slnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"src\\Middleware\\HttpsPolicy\\src\\Microsoft.AspNetCore.HttpsPolicy.csproj",
5757
"src\\Middleware\\Localization.Routing\\src\\Microsoft.AspNetCore.Localization.Routing.csproj",
5858
"src\\Middleware\\Localization\\src\\Microsoft.AspNetCore.Localization.csproj",
59+
"src\\Middleware\\OutputCaching\\src\\Microsoft.AspNetCore.OutputCaching.csproj",
5960
"src\\Middleware\\ResponseCaching.Abstractions\\src\\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj",
6061
"src\\Middleware\\ResponseCaching\\src\\Microsoft.AspNetCore.ResponseCaching.csproj",
6162
"src\\Middleware\\ResponseCompression\\src\\Microsoft.AspNetCore.ResponseCompression.csproj",

src/Framework/test/TestData.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static TestData()
7373
"Microsoft.AspNetCore.Mvc.RazorPages",
7474
"Microsoft.AspNetCore.Mvc.TagHelpers",
7575
"Microsoft.AspNetCore.Mvc.ViewFeatures",
76+
"Microsoft.AspNetCore.OutputCaching",
7677
"Microsoft.AspNetCore.Razor",
7778
"Microsoft.AspNetCore.Razor.Runtime",
7879
"Microsoft.AspNetCore.RequestDecompression",
@@ -209,6 +210,7 @@ static TestData()
209210
{ "Microsoft.AspNetCore.Mvc.RazorPages", "7.0.0.0" },
210211
{ "Microsoft.AspNetCore.Mvc.TagHelpers", "7.0.0.0" },
211212
{ "Microsoft.AspNetCore.Mvc.ViewFeatures", "7.0.0.0" },
213+
{ "Microsoft.AspNetCore.OutputCaching", "7.0.0.0" },
212214
{ "Microsoft.AspNetCore.Razor", "7.0.0.0" },
213215
{ "Microsoft.AspNetCore.Razor.Runtime", "7.0.0.0" },
214216
{ "Microsoft.AspNetCore.RequestDecompression", "7.0.0.0" },

src/Middleware/CORS/test/testassets/CorsMiddlewareWebSite/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
"applicationUrl": "https://localhost:61226;http://localhost:61227"
1010
}
1111
}
12-
}
12+
}

src/Middleware/Diagnostics/test/testassets/DatabaseErrorPageSample/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
"applicationUrl": "https://localhost:61218;http://localhost:61219"
1010
}
1111
}
12-
}
12+
}

src/Middleware/Diagnostics/test/testassets/DeveloperExceptionPageSample/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
"applicationUrl": "https://localhost:61228;http://localhost:61229"
1010
}
1111
}
12-
}
12+
}

src/Middleware/Diagnostics/test/testassets/ExceptionHandlerSample/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
"applicationUrl": "https://localhost:61220;http://localhost:61221"
1010
}
1111
}
12-
}
12+
}

0 commit comments

Comments
 (0)