Merge release/2.2 and replace submodules

* Replace the aspnet/JsonPatch git submodule and merge the master branch of its source to this repo
* Likewise for aspnet/DotNetTools
* And aspnet/HtmlAbstractions
* merge latest infrastructure changes from the release/2.2 branch
This commit is contained in:
Nate McMaster 2018-11-14 22:19:19 -08:00
No known key found for this signature in database
GPG Key ID: A778D9601BD78810
353 changed files with 26957 additions and 702 deletions

View File

@ -1,3 +1,4 @@
trigger:
- master
- release/*
@ -5,31 +6,18 @@ trigger:
jobs:
- template: jobs/default-build.yml
parameters:
jobName: PR_FastCheck
jobDisplayName: Fast Check
agentOs: Windows
jobName: Windows_FastCheck
jobDisplayName: Windows - Fast Check
buildArgs: "/t:FastCheck"
artifacts:
publish: false
- job: RepoBuilds
pool:
vmImage: vs2017-win2016
strategy:
maxParallel: 3
matrix:
DataProtection:
_FolderName: DataProtection
WebSockets:
_FolderName: WebSockets
steps:
- script: src/$(_FolderName)/build.cmd -ci
displayName: Run src/$(_FolderName)/build.cmd
- task: PublishTestResults@2
displayName: Publish test results
condition: always()
inputs:
testRunner: vstest
testResultsFiles: 'src/$(_FolderName)/artifacts/logs/**/*.trx'
- template: jobs/default-build.yml
parameters:
jobName: Windows_Build
jobDisplayName: "Build: Windows"
agentOs: Windows
beforeBuild:
- powershell: "& ./src/IISIntegration/tools/UpdateIISExpressCertificate.ps1"
displayName: Setup IISExpress test certificates
- template: jobs/iisintegration-job.yml
parameters:
TestGroupName: IIS

View File

@ -63,6 +63,7 @@ jobs:
- job: ${{ coalesce(parameters.jobName, parameters.agentOs) }}
displayName: ${{ coalesce(parameters.jobDisplayName, parameters.agentOs) }}
dependsOn: ${{ parameters.dependsOn }}
timeoutInMinutes: 90
workspace:
clean: all
strategy:

12
.gitmodules vendored
View File

@ -26,18 +26,10 @@
path = modules/Diagnostics
url = https://github.com/aspnet/Diagnostics.git
branch = master
[submodule "modules/DotNetTools"]
path = modules/DotNetTools
url = https://github.com/aspnet/DotNetTools.git
branch = master
[submodule "modules/Hosting"]
path = modules/Hosting
url = https://github.com/aspnet/Hosting.git
branch = master
[submodule "modules/HtmlAbstractions"]
path = modules/HtmlAbstractions
url = https://github.com/aspnet/HtmlAbstractions.git
branch = master
[submodule "modules/HttpAbstractions"]
path = modules/HttpAbstractions
url = https://github.com/aspnet/HttpAbstractions.git
@ -58,10 +50,6 @@
path = modules/JavaScriptServices
url = https://github.com/aspnet/JavaScriptServices.git
branch = master
[submodule "modules/JsonPatch"]
path = modules/JsonPatch
url = https://github.com/aspnet/JsonPatch.git
branch = master
[submodule "modules/KestrelHttpServer"]
path = modules/KestrelHttpServer
url = https://github.com/aspnet/KestrelHttpServer.git

View File

@ -17,6 +17,8 @@
replace PackageLicenseUrl with PackageLicenseExpression.
-->
<NoWarn>$(NoWarn);NU5125</NoWarn>
<!-- Suppress warnings about using SemVer 2.0. -->
<NoWarn>$(NoWarn);NU5105</NoWarn>
<!-- Contact email address for NuGet packages and Linux installers. -->
<MaintainerEmail>nugetaspnet@microsoft.com</MaintainerEmail>
@ -49,6 +51,16 @@
<BuildProjectReferences Condition=" '$(NoBuild)' == 'true' ">false</BuildProjectReferences>
</PropertyGroup>
<!-- Certificate names used for Authenticode signing. -->
<PropertyGroup Condition=" '$(DisableCodeSigning)' != 'true' ">
<AssemblySigningCertName>Microsoft400</AssemblySigningCertName>
<AssemblySigning3rdPartyCertName>3PartySHA2</AssemblySigning3rdPartyCertName>
<PowerShellSigningCertName>Microsoft400</PowerShellSigningCertName>
<PackageSigningCertName>NuGet</PackageSigningCertName>
<VsixSigningCertName>VsixSHA2</VsixSigningCertName>
<JarSigningCertName>MicrosoftJAR</JarSigningCertName>
</PropertyGroup>
<Import Project="build\external-dependencies.props" />
<Import Project="build\sources.props" />
@ -75,8 +87,16 @@
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
</PropertyGroup>
<PropertyGroup>
<StandardTestTfms>netcoreapp2.2;net461</StandardTestTfms>
</PropertyGroup>
<Import Project="eng\Dependencies.props" />
<Import Project="eng\PatchConfig.props" />
<Import Project="eng\ProjectReferences.props" />
<Import Project="eng\targets\RuntimeIdentifiers.props" />
<Import Project="eng\targets\Cpp.Common.props" Condition="'$(MSBuildProjectExtension)' == '.vcxproj'" />
<Import Project="eng\targets\CSharp.Common.props" Condition="'$(MSBuildProjectExtension)' == '.csproj'" />
<Import Project="eng\targets\SharedFx.Common.props" Condition="'$(MSBuildProjectExtension)' == '.shfxproj'" />
<Import Project="eng\targets\Wix.Common.props" Condition="'$(MSBuildProjectExtension)' == '.wixproj'" />

View File

@ -1,9 +1,46 @@
<Project>
<!-- Properties which should be set after the project has been evaluated -->
<PropertyGroup Condition=" '$(MSBuildProjectExtension)' == '.csproj' ">
<PackageId Condition=" '$(PackageId)' == '' ">$(AssemblyName)</PackageId>
<IsPackable Condition="'$(IsPackable)' == '' AND ( '$(IsTestProject)' == 'true' OR '$(IsTestAssetProject)' == 'true' OR '$(IsBenchmarkProject)' == 'true' OR '$(IsSampleProject)' == 'true' ) ">false</IsPackable>
</PropertyGroup>
<Import Project="eng\Baseline.props" />
<PropertyGroup Condition=" '$(IsPackable)' != 'false' AND '$(AspNetCorePatchVersion)' != '0' ">
<!-- Always include framework metapackages in patch updates. -->
<IsPackageInThisPatch Condition="'$(IsFrameworkMetapackage)' == 'true'">true</IsPackageInThisPatch>
<IsPackageInThisPatch Condition="'$(IsPackageInThisPatch)' == ''">$(PackagesInPatch.Contains(' $(PackageId);'))</IsPackageInThisPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(IsPackable)' != 'false' AND '$(IsServicingBuild)' == 'true' ">
<!-- Used to distinguish between packages building -->
<IsPackableInNonServicingBuild>true</IsPackableInNonServicingBuild>
<!-- Suppress creation of .nupkg for servicing builds. -->
<IsPackable Condition=" '$(IsPackageInThisPatch)' != 'true' ">false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition=" '$(IsPackageInThisPatch)' != 'true' AND '$(BaselinePackageVersion)' != '' ">
<!-- This keeps assembly and package versions consistent across patches. If a package is not included in a patch, its version should stay at the baseline. -->
<AssemblyVersion>$(BaselinePackageVersion).0</AssemblyVersion>
<!--
Ideally, we would also set the project version to match the baseline in case NuGet turns a ProjectReference into a nuspec depenendency, but
NuGet does not currently handle conflicts between packages and projects which have the same package id/version.
See https://github.com/NuGet/Home/issues/6795.
Because we still use static analysis to scrape versions, only set this during static analysis, which can be detected by checking for both NoBuild and DesignTimeBuild.
-->
<Version Condition="'$(NoBuild)' == 'true' AND '$(DesignTimeBuild)' == 'true'">$(BaselinePackageVersion)</Version>
<PackageVersion Condition="'$(NoBuild)' == 'true' AND '$(DesignTimeBuild)' == 'true'">$(BaselinePackageVersion)</PackageVersion>
</PropertyGroup>
<PropertyGroup>
<!-- Implementation projects are the projects which produce nuget packages or shipping assemblies. -->
<IsImplementationProject Condition=" '$(IsImplementationProject)' == '' AND '$(IsTestAssetProject)' != 'true' AND '$(IsTestProject)' != 'true' AND '$(IsBenchmarkProject)' != 'true' AND '$(IsSampleProject)' != 'true' ">true</IsImplementationProject>
<!-- Suppress KoreBuild warnings about the mismatch of repo version and local project version. The versioning in this mega repo is sufficiently complicated that KoreBuild's validation isn't helpful. -->
<VerifyVersion>false</VerifyVersion>
<EnableApiCheck Condition=" '$(EnableApiCheck)' != '' ">$(IsImplementationProject)</EnableApiCheck>
<IsPackable Condition="'$(IsPackable)' == '' AND '$(IsImplementationProject)' == 'true' ">true</IsPackable>
<IsPackable Condition="'$(IsPackable)' == '' ">false</IsPackable>
@ -16,6 +53,7 @@
</PropertyGroup>
<Import Project="eng\targets\Cpp.Common.targets" Condition="'$(MSBuildProjectExtension)' == '.vcxproj'" />
<Import Project="eng\targets\CSharp.Common.targets" Condition="'$(MSBuildProjectExtension)' == '.csproj'" />
<Import Project="eng\targets\SharedFx.Common.targets" Condition="'$(MSBuildProjectExtension)' == '.shfxproj'" />
<Import Project="eng\targets\Wix.Common.targets" Condition="'$(MSBuildProjectExtension)' == '.wixproj'" />
</Project>

View File

@ -43,6 +43,7 @@
<FilesToSign Include="Microsoft.Extensions.Options.DataAnnotations.dll" Certificate="$(AssemblySigningCertName)" Container="Microsoft.AspNetCore.App" />
<FilesToSign Include="Microsoft.Extensions.Options.dll" Certificate="$(AssemblySigningCertName)" Container="Microsoft.AspNetCore.App" />
<FilesToSign Include="Microsoft.Extensions.Primitives.dll" Certificate="$(AssemblySigningCertName)" Container="Microsoft.AspNetCore.App" />
<FilesToSign Include="Microsoft.Extensions.WebEncoders.dll" Certificate="$(AssemblySigningCertName)" Container="Microsoft.AspNetCore.App" />
<!-- These files came from the aspnet/EntityFrameworkCore build, but have to be re-signed because we crossgen them. -->
<FilesToSign Include="Microsoft.EntityFrameworkCore.Abstractions.dll" Certificate="$(AssemblySigningCertName)" Container="Microsoft.AspNetCore.App" />
<FilesToSign Include="Microsoft.EntityFrameworkCore.Design.dll" Certificate="$(AssemblySigningCertName)" Container="Microsoft.AspNetCore.App" />

View File

@ -4,7 +4,7 @@
<CodeSignDependsOn>$(CodeSignDependsOn);CollectFileSignInfo</CodeSignDependsOn>
</PropertyGroup>
<Target Name="CollectFileSignInfo" DependsOnTargets="_PrepareRepositories">
<Target Name="CollectFileSignInfo" DependsOnTargets="_PrepareRepositories;GetProjectArtifactInfo;GetFxProjectArtifactInfo">
<ItemGroup>
<_RepositoryProject Remove="@(_RepositoryProject)" />
@ -12,6 +12,10 @@
<AdditionalProperties>RepositoryRoot=%(Repository.RootPath)</AdditionalProperties>
<Build>%(Repository.Build)</Build>
</_RepositoryProject>
<_ShippedRepositoryProject Include="$(MSBuildProjectFullPath)" Condition="'%(ShippedRepository.Identity)' != ''">
<AdditionalProperties>RepositoryRoot=%(ShippedRepository.RootPath)</AdditionalProperties>
<Build>false</Build>
</_ShippedRepositoryProject>
</ItemGroup>
<PropertyGroup>
@ -28,21 +32,37 @@
</PropertyGroup>
<MSBuild Projects="@(_RepositoryProject)"
Condition="@(_RepositoryProject->Count()) != 0"
Targets="_GetFileSignInfo"
Properties="$(GetFileSignInfoProps);$(DesignTimeBuildProps);DesignTimeBuild=true;Configuration=$(Configuration);BuildNumber=$(BuildNumber);CustomAfterKoreBuildTargets=$(MSBuildThisFileFullPath)"
BuildInParallel="true">
<Output TaskParameter="TargetOutputs" ItemName="_RepoFileSignInfo" />
</MSBuild>
<MSBuild Projects="@(_ShippedRepositoryProject)"
Condition="@(_ShippedRepositoryProject->Count()) != 0"
Targets="_GetFileSignInfo"
Properties="$(GetFileSignInfoProps);$(DesignTimeBuildProps);IsFinalBuild=true;DesignTimeBuild=true;Configuration=$(Configuration);BuildNumber=$(BuildNumber);CustomAfterKoreBuildTargets=$(MSBuildThisFileFullPath)"
BuildInParallel="true">
<Output TaskParameter="TargetOutputs" ItemName="_ShippedRepoFileSignInfo" />
</MSBuild>
<ItemGroup>
<!-- If repos were not built, only use this info to collect the mapping of FileName -> Certificate. Otherwise, include .nupkg and .zips in signing. -->
<_FilesToSign Include="@(_RepoFileSignInfo)" Condition="'%(_RepoFileSignInfo.IsFileToSign)' == 'true' AND ('$(_ReposWereBuilt)' == 'true' OR '%(_RepoFileSignInfo.Container)' != '' ) " />
<_FilesToSign Include="@(_ShippedRepoFileSignInfo)" Condition="'%(_ShippedRepoFileSignInfo.IsFileToSign)' == 'true' AND '%(_ShippedRepoFileSignInfo.Container)' != '' " />
<FilesToSign Include="@(_FilesToSign)" />
<!-- Normalize FilesToExcludeFromSigning to filename + extension. -->
<_Temp Remove="@(_Temp)" />
<_Temp Include="@(FilesToExcludeFromSigning)" />
<FilesToExcludeFromSigning Remove="@(FilesToExcludeFromSigning)" />
<FilesToExcludeFromSigning Include="@(_Temp->'%(FileName)%(Extension)')" />
<_Temp Remove="@(_Temp)" />
<FilesToExcludeFromSigning Include="@(_ShippedRepoFileSignInfo->'%(FileName)%(Extension)')" Condition="'%(_ShippedRepoFileSignInfo.IsFileToExcludeFromSign)' == 'true'" />
<FilesToExcludeFromSigning Include="@(_RepoFileSignInfo->'%(FileName)%(Extension)')" Condition="'%(_RepoFileSignInfo.IsFileToExcludeFromSign)' == 'true'" />
<!-- Workaround for the way we have both repo and Universe builds, crossgen AND uncrossgened outputs. This prevents duplicate configuration between 'exclude' and 'sign' options. -->
<FilesToExcludeFromSigning Remove="@(FilesToSign->'%(FileName)%(Extension)')" />
<FilesToExcludeFromSigning Remove="@(_FilesToSign->'%(FileName)%(Extension)')" />
</ItemGroup>
</Target>

View File

@ -8,9 +8,7 @@
<ArchiveProjects Include="$(RepositoryRoot)src\PackageArchive\Archive.*\*.*proj" />
</ItemGroup>
<Target Name="BuildFallbackArchive" DependsOnTargets="ResolveRepoInfo;GeneratePropsFiles">
<Target Name="BuildFallbackArchive" DependsOnTargets="GetProjectArtifactInfo;GetFxProjectArtifactInfo;ResolveRepoInfo;GeneratePropsFiles">
<PropertyGroup>
<ArchiveBuildProps>
DotNetRestoreSourcePropsPath=$(GeneratedRestoreSourcesPropsPath);

View File

@ -2,21 +2,22 @@
<PropertyGroup>
<UnitTestFxProject>$(RepositoryRoot)src\Framework\Framework.UnitTests\Framework.UnitTests.csproj</UnitTestFxProject>
<UnitTestFxProject>$([MSBuild]::NormalizePath($(UnitTestFxProject)))</UnitTestFxProject>
<CodeSignDependsOn>$(CodeSignDependsOn);GetSharedFxFilesToSign</CodeSignDependsOn>
<CodeSignDependsOn Condition="'$(_ProjectsOnly)' != 'true'">$(CodeSignDependsOn);GetSharedFxFilesToSign</CodeSignDependsOn>
<BuildSharedFxDependsOn>_BuildSharedFxProjects;TestSharedFx</BuildSharedFxDependsOn>
<BuildSharedFxDependsOn Condition="'$(TestOnly)' != 'true'">$(BuildSharedFxDependsOn);CodeSign</BuildSharedFxDependsOn>
<RedistNetCorePath>$(IntermediateDir)ar\$(SharedFxRid)\</RedistNetCorePath>
<GetArtifactInfoDependsOn>$(GetArtifactInfo);GetFxProjectArtifactInfo</GetArtifactInfoDependsOn>
<BuildRuntimeSiteExtension Condition="'$(SharedFxRid)' == 'win-x64' OR '$(SharedFxRid)' == 'win-x86'">true</BuildRuntimeSiteExtension>
</PropertyGroup>
<ItemGroup>
<ProjectToBuild Include="$(RepositoryRoot)src\Framework\**\*.pkgproj" />
<ProjectToBuild Include="$(RepositoryRoot)src\Framework\**\*.shfxproj" />
<ProjectToBuild Include="$(UnitTestFxProject)" />
<ProjectToBuild Condition=" '$(BuildRuntimeArchive)' != 'false' " Include="$(RepositoryRoot)src\Installers\Archive\*.*proj" />
<ProjectToBuild Condition=" '$(BuildRuntimeSiteExtension)' == 'true' " Include="$(RepositoryRoot)src\Installers\RuntimeSiteExtension\Microsoft.AspNetCore.Runtime.SiteExtension.pkgproj" />
<ProjectToBuild Condition=" '$(SharedFxRid)' == 'linux-x64' AND '$(LinuxInstallerType)' == 'deb' " Include="$(RepositoryRoot)src\Installers\Debian\*.*proj" />
<ProjectToBuild Condition=" '$(SharedFxRid)' == 'linux-x64' AND '$(LinuxInstallerType)' == 'rpm' " Include="$(RepositoryRoot)src\Installers\Rpm\*.*proj" />
<FxProjectToBuild Include="$(RepositoryRoot)src\Framework\**\*.pkgproj" />
<FxProjectToBuild Include="$(RepositoryRoot)src\Framework\**\*.shfxproj" />
<FxProjectToBuild Include="$(UnitTestFxProject)" />
<FxProjectToBuild Condition=" '$(BuildRuntimeArchive)' != 'false' " Include="$(RepositoryRoot)src\Installers\Archive\*.*proj" />
<FxProjectToBuild Condition=" '$(BuildRuntimeSiteExtension)' == 'true' " Include="$(RepositoryRoot)src\Installers\RuntimeSiteExtension\Microsoft.AspNetCore.Runtime.SiteExtension.pkgproj" />
<FxProjectToBuild Condition=" '$(SharedFxRid)' == 'linux-x64' AND '$(LinuxInstallerType)' == 'deb' " Include="$(RepositoryRoot)src\Installers\Debian\*.*proj" />
<FxProjectToBuild Condition=" '$(SharedFxRid)' == 'linux-x64' AND '$(LinuxInstallerType)' == 'rpm' " Include="$(RepositoryRoot)src\Installers\Rpm\*.*proj" />
</ItemGroup>
<Target Name="BuildSharedFx" DependsOnTargets="$(BuildSharedFxDependsOn)" />
@ -43,7 +44,7 @@
<Target Name="_BuildSharedFxProjects" DependsOnTargets="GeneratePropsFiles;ResolveCommitHash">
<PropertyGroup>
<_RestoreGraphProjectInput>@(ProjectToBuild)</_RestoreGraphProjectInput>
<_RestoreGraphProjectInput>@(FxProjectToBuild)</_RestoreGraphProjectInput>
<SharedFxBuildProperties>
$(BuildProperties);
SharedFxRid=$(SharedFxRid);
@ -58,11 +59,11 @@
Targets="Restore"
Properties="$(SharedFxBuildProperties);RestoreGraphProjectInput=$(_RestoreGraphProjectInput);_DummyTarget=Restore" />
<MSBuild Projects="@(ProjectToBuild)"
<MSBuild Projects="@(FxProjectToBuild)"
Properties="$(SharedFxBuildProperties)"
BuildInParallel="true" />
<MSBuild Projects="@(ProjectToBuild)"
<MSBuild Projects="@(FxProjectToBuild)"
Targets="Pack"
Properties="$(SharedFxBuildProperties);NoBuild=true"
BuildInParallel="true"
@ -100,4 +101,35 @@
<Error Text="SharedFx.UnitTests failed with exit code '$(VsTestExitCode)'." Condition=" $(VsTestExitCode) != 0 " />
</Target>
<Target Name="GetFxProjectArtifactInfo" Returns="@(ArtifactInfo)">
<PropertyGroup>
<_InspectionTargetsFile>$(MSBuildProjectDirectory)\Project.Inspection.targets</_InspectionTargetsFile>
</PropertyGroup>
<ItemGroup>
<_Temp Remove="@(_Temp)" />
</ItemGroup>
<MSBuild Targets="GetArtifactInfo"
Projects="@(FxProjectToBuild)"
Condition="@(FxProjectToBuild->Count()) != 0"
Properties="$(BuildProperties);DesignTimeBuild=true;EnableApiCheck=false;NoBuild=true;CustomAfterMicrosoftCommonTargets=$(_InspectionTargetsFile);CustomAfterMicrosoftCommonCrossTargetingTargets=$(_InspectionTargetsFile)"
BuildInParallel="$(BuildInParallel)"
RemoveProperties="$(_BuildPropertiesToRemove)">
<Output TaskParameter="TargetOutputs" ItemName="_Temp" />
</MSBuild>
<ItemGroup>
<!-- Output from this target may include items representing assemblies inside the nupkg. -->
<ArtifactInfo Include="@(_Temp)" Condition="'%(_Temp.Container)' == ''" />
<!-- Nupkgs or assemblies in the nupkg that should be signed -->
<FilesToSign Include="@(_Temp)" Condition=" '%(_Temp.ShouldBeSigned)' == 'true' " />
<!-- Nupkgs or assemblies in the nupkg that should not be signed -->
<FilesToExcludeFromSigning Include="@(_Temp)" Condition=" '%(_Temp.ShouldBeSigned)' != 'true' " />
</ItemGroup>
</Target>
</Project>

View File

@ -175,7 +175,6 @@
<PackageArtifact Include="Microsoft.Extensions.Identity.Stores" Category="ship" />
<PackageArtifact Include="Microsoft.Extensions.Localization.Abstractions" Category="ship" />
<PackageArtifact Include="Microsoft.Extensions.Localization" Category="ship" />
<PackageArtifact Include="Microsoft.Extensions.WebEncoders" Category="ship" />
<PackageArtifact Include="Microsoft.Net.Http.Headers" Category="ship" />
<PackageArtifact Include="Microsoft.NET.Sdk.Razor" Category="ship" />
<PackageArtifact Include="Microsoft.Owin.Security.Interop" Category="ship" />

View File

@ -7,16 +7,12 @@
</ItemDefinitionGroup>
<ItemGroup>
<RepositoryBuildOrder Include="JsonPatch" Order="1" />
<RepositoryBuildOrder Include="DotNetTools" Order="1" />
<RepositoryBuildOrder Include="HtmlAbstractions" Order="1" />
<RepositoryBuildOrder Include="Razor" Order="6" />
<RepositoryBuildOrder Include="HttpAbstractions" Order="6" />
<RepositoryBuildOrder Include="HttpClientFactory" Order="6" />
<RepositoryBuildOrder Include="Hosting" Order="7" />
<RepositoryBuildOrder Include="KestrelHttpServer" Order="8" />
<RepositoryBuildOrder Include="HttpSysServer" Order="8" />
<RepositoryBuildOrder Include="DataProtection" Order="9" RootPath="$(RepositoryRoot)src\DataProtection\" />
<RepositoryBuildOrder Include="BasicMiddleware" Order="9" />
<RepositoryBuildOrder Include="Antiforgery" Order="10" />
<RepositoryBuildOrder Include="IISIntegration" Order="10" RootPath="$(RepositoryRoot)src\IISIntegration\" />
@ -28,7 +24,6 @@
<RepositoryBuildOrder Include="Routing" Order="12" />
<RepositoryBuildOrder Include="Diagnostics" Order="12" />
<RepositoryBuildOrder Include="Localization" Order="13" />
<RepositoryBuildOrder Include="WebSockets" Order="13" RootPath="$(RepositoryRoot)src\WebSockets\" />
<RepositoryBuildOrder Include="Security" Order="13" />
<RepositoryBuildOrder Include="MetaPackages" Order="13" />
<RepositoryBuildOrder Include="Mvc" Order="14" />

View File

@ -1,7 +1,7 @@
<!-- This file is temporary while we rework dependencies management. It is used when building individual folders as if they were repos. -->
<Project>
<PropertyGroup>
<InternalAspNetCoreSdkPackageVersion Condition="'$(InternalAspNetCoreSdkPackageVersion)' == ''">3.0.0-alpha1-20181108.8</InternalAspNetCoreSdkPackageVersion>
<InternalAspNetCoreSdkPackageVersion Condition="'$(InternalAspNetCoreSdkPackageVersion)' == ''">3.0.0-build-20181114.5</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreAspNetCoreModulePackageVersion>3.0.0-alpha1-10717</MicrosoftAspNetCoreAspNetCoreModulePackageVersion>
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>3.0.0-alpha1-10717</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
<MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>3.0.0-alpha1-10717</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>

View File

@ -31,67 +31,68 @@
<SystemThreadingTasksExtensionsPackageVersion>4.6.0-preview1-26907-04</SystemThreadingTasksExtensionsPackageVersion>
<SystemValueTuplePackageVersion>4.6.0-preview1-26829-04</SystemValueTuplePackageVersion>
<!-- Packages from aspnet/Extensions -->
<InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview-181108-06</InternalAspNetCoreAnalyzersPackageVersion>
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview-181108-06</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview-181108-06</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsCachingSqlServerPackageVersion>
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
<MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDependencyInjectionSpecificationTestsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsDependencyInjectionSpecificationTestsPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>
<MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>
<MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsObjectPoolPackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftExtensionsProcessSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsProcessSourcesPackageVersion>
<MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>
<MicrosoftExtensionsPropertyHelperSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsPropertyHelperSourcesPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftExtensionsStackTraceSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsStackTraceSourcesPackageVersion>
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
<MicrosoftExtensionsWebEncodersSourcesPackageVersion>3.0.0-preview-181108-06</MicrosoftExtensionsWebEncodersSourcesPackageVersion>
<InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview-181113-11</InternalAspNetCoreAnalyzersPackageVersion>
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
<MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview-181113-11</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCachingSqlServerPackageVersion>
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
<MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsDependencyInjectionSpecificationTestsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDependencyInjectionSpecificationTestsPackageVersion>
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion>
<MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion>
<MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsObjectPoolPackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftExtensionsProcessSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsProcessSourcesPackageVersion>
<MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsPropertyActivatorSourcesPackageVersion>
<MicrosoftExtensionsPropertyHelperSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsPropertyHelperSourcesPackageVersion>
<MicrosoftExtensionsRazorViewsSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsRazorViewsSourcesPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftExtensionsStackTraceSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsStackTraceSourcesPackageVersion>
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
<MicrosoftExtensionsWebEncodersSourcesPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsWebEncodersSourcesPackageVersion>
<MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview-181113-11</MicrosoftExtensionsWebEncodersPackageVersion>
<!-- Packages from aspnet/EntityFrameworkCore -->
<MicrosoftEntityFrameworkCoreAbstractionsPackageVersion>3.0.0-preview-181109-02</MicrosoftEntityFrameworkCoreAbstractionsPackageVersion>
<MicrosoftEntityFrameworkCoreAnalyzersPackageVersion>3.0.0-preview-181109-02</MicrosoftEntityFrameworkCoreAnalyzersPackageVersion>
@ -116,10 +117,12 @@
<!-- Determined by build tools -->
<InternalAspNetCoreSdkPackageVersion>$(KoreBuildVersion)</InternalAspNetCoreSdkPackageVersion>
<InternalAspNetCoreSiteExtensionSdkPackageVersion>$(KoreBuildVersion)</InternalAspNetCoreSiteExtensionSdkPackageVersion>
<InternalAspNetCoreSdkPackageVersion Condition=" '$(KoreBuildVersion)' == '' ">2.2.1-build-20181114.3</InternalAspNetCoreSdkPackageVersion>
</PropertyGroup>
<!-- These are package versions that should not be overridden or updated by automation. -->
<PropertyGroup Label="Package Versions: Pinned">
<!-- 3rd party dependencies -->
<AngleSharpPackageVersion>0.9.9</AngleSharpPackageVersion>
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
@ -212,6 +215,7 @@
<PollyPackageVersion>6.0.1</PollyPackageVersion>
<SeleniumFirefoxWebDriverPackageVersion>0.20.0</SeleniumFirefoxWebDriverPackageVersion>
<SeleniumSupportPackageVersion>3.12.1</SeleniumSupportPackageVersion>
<SeleniumWebDriverChromeDriverPackageVersion>2.43.0</SeleniumWebDriverChromeDriverPackageVersion>
<SeleniumWebDriverMicrosoftDriverPackageVersion>17.17134.0</SeleniumWebDriverMicrosoftDriverPackageVersion>
<SeleniumWebDriverPackageVersion>3.12.1</SeleniumWebDriverPackageVersion>
<SerilogExtensionsLoggingPackageVersion>1.4.0</SerilogExtensionsLoggingPackageVersion>

View File

@ -71,6 +71,7 @@
<ExternalDependency Include="Microsoft.Extensions.TypeNameHelper.Sources" Version="$(MicrosoftExtensionsTypeNameHelperSourcesPackageVersion)" />
<ExternalDependency Include="Microsoft.Extensions.ValueStopwatch.Sources" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" />
<ExternalDependency Include="Microsoft.Extensions.WebEncoders.Sources" Version="$(MicrosoftExtensionsWebEncodersSourcesPackageVersion)" />
<ExternalDependency Include="Microsoft.Extensions.WebEncoders" Version="$(MicrosoftExtensionsWebEncodersPackageVersion)" />
<ExternalDependency Include="Microsoft.EntityFrameworkCore.Abstractions" Version="$(MicrosoftEntityFrameworkCoreAbstractionsPackageVersion)" />
<ExternalDependency Include="Microsoft.EntityFrameworkCore.Analyzers" Version="$(MicrosoftEntityFrameworkCoreAnalyzersPackageVersion)" />
<ExternalDependency Include="Microsoft.EntityFrameworkCore.Design" Version="$(MicrosoftEntityFrameworkCoreDesignPackageVersion)" />

View File

@ -4,6 +4,8 @@
<PropertyGroup>
<!-- This repo does not have solutions to build -->
<DisableDefaultTargets>true</DisableDefaultTargets>
<DisableDefaultItems>true</DisableDefaultItems>
<BuildSolutions>false</BuildSolutions>
<SkipTests>false</SkipTests>
<SkipTests Condition="'$(CompileOnly)' == 'true'">true</SkipTests>
@ -13,8 +15,6 @@
<DependencyPackageDir>$(RepositoryRoot).deps\build\</DependencyPackageDir>
<SignedDependencyPackageDir>$(RepositoryRoot).deps\Signed\Packages\</SignedDependencyPackageDir>
<!-- SignCheck currently fails when verifying vsix files. See https://github.com/dotnet/arcade/issues/1306. -->
<DisableSignCheck>true</DisableSignCheck>
<SignCheckExclusionsFile>$(RepositoryRoot)eng\signcheck.exclusions.txt</SignCheckExclusionsFile>
<!-- This creates false-positives on many of the native .dll's we produce or re-distribute from other teams. -->
<DisableSignCheckStrongName>true</DisableSignCheckStrongName>
@ -49,6 +49,22 @@
<SharedFrameworkName Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectToExclude Include="
$(RepositoryRoot)src\Middleware\WebSockets\samples\**\*.csproj;
$(RepositoryRoot)src\Tools\dotnet-watch\test\TestProjects\**\*.csproj;
" />
<ProjectToBuild Include="
$(RepositoryRoot)src\Features\JsonPatch\**\*.*proj;
$(RepositoryRoot)src\DataProtection\**\*.*proj;
$(RepositoryRoot)src\Html\**\*.*proj;
$(RepositoryRoot)src\Tools\**\*.*proj;
$(RepositoryRoot)src\Middleware\**\*.*proj;
"
Exclude="@(ProjectToExclude)" />
</ItemGroup>
<!-- Properties for publishing -->
<PropertyGroup>
<!-- myget = non-orchestrated builds -->

View File

@ -15,20 +15,60 @@
<GeneratedRestoreSourcesPropsPath>$(IntermediateDir)sources.g.props</GeneratedRestoreSourcesPropsPath>
<GeneratedBrandingPropsPath>$(IntermediateDir)branding.g.props</GeneratedBrandingPropsPath>
<PrepareDependsOn>SetTeamCityBuildNumberToVersion;$(PrepareDependsOn);VerifyPackageArtifactConfig;VerifyExternalDependencyConfig;PrepareOutputPaths</PrepareDependsOn>
<PrepareDependsOn>SetTeamCityBuildNumberToVersion;$(PrepareDependsOn)</PrepareDependsOn>
<PrepareDependsOn Condition="'$(_ProjectsOnly)' != 'true'">$(PrepareDependsOn);VerifyPackageArtifactConfig;VerifyExternalDependencyConfig;PrepareOutputPaths</PrepareDependsOn>
<CleanDependsOn>$(CleanDependsOn);CleanArtifacts;CleanRepoArtifacts</CleanDependsOn>
<RestoreDependsOn>$(RestoreDependsOn);InstallDotNet</RestoreDependsOn>
<CompileDependsOn>$(CompileDependsOn);BuildRepositories;BuildSharedFx</CompileDependsOn>
<PackageDependsOn Condition="'$(TestOnly)' != 'true'">$(PackageDependsOn);CheckExpectedPackagesExist;CodeSign</PackageDependsOn>
<TestDependsOn>$(TestDependsOn);_TestRepositories</TestDependsOn>
<GetArtifactInfoDependsOn>$(GetArtifactInfoDependsOn);ResolveRepoInfo</GetArtifactInfoDependsOn>
<RestoreDependsOn>$(RestoreDependsOn);InstallDotNet;RestoreProjects</RestoreDependsOn>
<CompileDependsOn>$(CompileDependsOn);BuildProjects</CompileDependsOn>
<CompileDependsOn Condition="'$(_ProjectsOnly)' != 'true'">$(CompileDependsOn);PackProjects;BuildRepositories;BuildSharedFx</CompileDependsOn>
<PackageDependsOn Condition=" '$(_ProjectsOnly)' == 'true'">$(PackageDependsOn);PackProjects</PackageDependsOn>
<PackageDependsOn Condition="'$(TestOnly)' != 'true' AND '$(_ProjectsOnly)' != 'true'">$(PackageDependsOn);CheckExpectedPackagesExist</PackageDependsOn>
<PackageDependsOn Condition="'$(TestOnly)' != 'true'">$(PackageDependsOn);CodeSign</PackageDependsOn>
<TestDependsOn>$(TestDependsOn);TestProjects</TestDependsOn>
<TestDependsOn Condition="'$(_ProjectsOnly)' != 'true'">$(TestDependsOn);_TestRepositories</TestDependsOn>
<GetArtifactInfoDependsOn>$(GetArtifactInfoDependsOn);GetProjectArtifactInfo</GetArtifactInfoDependsOn>
<GetArtifactInfoDependsOn Condition="'$(_ProjectsOnly)' != 'true'">$(GetArtifactInfoDependsOn);ResolveRepoInfo</GetArtifactInfoDependsOn>
</PropertyGroup>
<Target Name="PrepareOutputPaths">
<MakeDir Directories="$(ArtifactsDir);$(BuildDir)" />
</Target>
<Target Name="ResolveRepoInfo" DependsOnTargets="_PrepareRepositories;GetLineupPackageInfo">
<Target Name="GenerateProjectList" DependsOnTargets="ResolveProjects">
<MSBuild Projects="@(ProjectToBuild)"
Targets="GetReferencesProvided"
BuildInParallel="true"
SkipNonexistentTargets="true"
SkipNonexistentProjects="true" >
<Output TaskParameter="TargetOutputs" ItemName="_ProjectReferenceProvider"/>
</MSBuild>
<PropertyGroup>
<ProjectListFile>$(MSBuildThisFileDirectory)..\eng\ProjectReferences.props</ProjectListFile>
<ProjectListContent>
<![CDATA[
<!-- This file is automatically generated. Run `build.cmd /t:GenerateProjectList` to update. -->
<Project>
<ItemGroup>
@(_ProjectReferenceProvider->'<ProjectReferenceProvider Include="%(Identity)" ProjectPath="%24(RepositoryRoot)%(ProjectFileRelativePath)" />', '%0A ')
</ItemGroup>
</Project>
]]>
</ProjectListContent>
</PropertyGroup>
<WriteLinesToFile File="$(ProjectListFile)" Lines="$(ProjectListContent)" Overwrite="true" />
</Target>
<Target Name="_ResolveProjectArtifactsInfoShipped" AfterTargets="GetProjectArtifactInfo">
<ItemGroup>
<ShippedArtifactInfo Include="@(ArtifactInfo)" Condition="'%(ArtifactInfo.IsShipped)' == 'true'" />
<ArtifactInfo Remove="@(ShippedArtifactInfo)" />
</ItemGroup>
</Target>
<Target Name="ResolveRepoInfo" DependsOnTargets="_ResolveProjectArtifactsInfoShipped;_PrepareRepositories;GetLineupPackageInfo">
<!-- We need to pass the NETCoreApp package versions to msbuild so that it doesn't complain about us using a different one than it was restored against. -->
<PropertyGroup>
<DesignTimeBuildProps>$(BuildProperties);MicrosoftNETCoreAppPackageVersion=$(MicrosoftNETCoreAppPackageVersion);</DesignTimeBuildProps>
@ -238,14 +278,15 @@
<Target Name="BuildRepositories"
DependsOnTargets="_PrepareRepositories;GeneratePropsFiles;ComputeGraph;_BuildRepositories" />
<Target Name="ListExpectedPackages" DependsOnTargets="ResolveRepoInfo">
<Target Name="ListExpectedPackages" DependsOnTargets="GetProjectArtifactInfo;GetFxProjectArtifactInfo;ResolveRepoInfo">
<WriteLinesToFile File="$(RepositoryRoot)artifacts\packages.csv" Lines="PackageId,Version;@(ArtifactInfo->WithMetadataValue('ArtifactType', 'NuGetPackage')->'%(PackageId),%(Version)')" Overwrite="true" />
</Target>
<Target Name="ComputeGraph" DependsOnTargets="ResolveRepoInfo;GeneratePropsFiles">
<Target Name="ComputeGraph" DependsOnTargets="GetProjectArtifactInfo;GetFxProjectArtifactInfo;ResolveRepoInfo;GeneratePropsFiles">
<ItemGroup>
<_UndeclaredPackageArtifact Include="%(ArtifactInfo.PackageId)" Condition="'%(ArtifactInfo.ArtifactType)' == 'NuGetPackage'" />
<_UndeclaredPackageArtifact Remove="@(PackageArtifact)" />
<RepositoryBuildOrder Remove="@(ShippedRepository)" />
</ItemGroup>
<Error Text="Undeclared package artifacts. Add these to artifacts.props:%0A - @(_UndeclaredPackageArtifact, '%0A - ')"

View File

@ -7,6 +7,13 @@
$(DotNetAdditionalRestoreSources);
$(DotNetRestoreSources);
</RestoreSources>
<!-- This is the 2.2.0 RTM feed. This is necessary until 2.2.0 ships to nuget.org -->
<RestoreSources>
$(RestoreSources);
https://dotnetfeed.blob.core.windows.net/orchestrated-release-2-2/20181110-02/final/index.json;
</RestoreSources>
<RestoreSources Condition=" '$(DotNetBuildOffline)' != 'true' ">
$(RestoreSources);
https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;

View File

@ -41,18 +41,14 @@
<Repository Include="AzureIntegration" />
<Repository Include="BasicMiddleware" />
<Repository Include="CORS" />
<Repository Include="DataProtection" RootPath="$(RepositoryRoot)src\DataProtection\" />
<Repository Include="Diagnostics" />
<Repository Include="DotNetTools" />
<Repository Include="Hosting" />
<Repository Include="HtmlAbstractions" />
<Repository Include="HttpAbstractions" />
<Repository Include="HttpClientFactory" />
<Repository Include="HttpSysServer" />
<Repository Include="Identity" />
<Repository Include="IISIntegration" RootPath="$(RepositoryRoot)src\IISIntegration\" />
<Repository Include="JavaScriptServices" />
<Repository Include="JsonPatch" />
<Repository Include="KestrelHttpServer" />
<Repository Include="Localization" />
<Repository Include="MetaPackages" PatchPolicy="CascadeVersions" />
@ -65,7 +61,6 @@
<Repository Include="SignalR" />
<Repository Include="StaticFiles" />
<Repository Include="Templating" PatchPolicy="AlwaysUpdateAndCascadeVersions" />
<Repository Include="WebSockets" RootPath="$(RepositoryRoot)src\WebSockets\" />
<!-- Test-only repos -->
<Repository Include="AuthSamples" PatchPolicy="AlwaysUpdateAndCascadeVersions" />

View File

@ -6,6 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Remove="Internal.AspNetCore.Sdk" />
<PackageReference Include="Microsoft.DotNet.Archive" Version="$(MicrosoftDotNetArchivePackageVersion)" />
<PackageReference Include="NuGet.Build.Tasks" Version="$(NuGetInMSBuildVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(DevDependency_MicrosoftExtensionsDependencyModelPackageVersion)" PrivateAssets="All" />

View File

@ -0,0 +1,41 @@
Preparing new servicing updates
===============================
In order to prepare this repo to build a new servicing update, the following changes need to be made.
* Increment the patch version in the [version.props](/version.props) file in the repository root.
```diff
- <AspNetCorePatchVersion>7</AspNetCorePatchVersion>
+ <AspNetCorePatchVersion>8</AspNetCorePatchVersion>
```
* Update the package archive baselines. This is used to make sure each build of the package archives we give to Azure only contains new files and does
not require overwriting existing files. See [src/PackageArchive/ZipManifestGenerator/](/src/PackageArchive/ZipManifestGenerator/README.md) for instructions on how to run this tool.
* Update the package baselines. This is used to ensure packages keep a consistent set of dependencies between releases.
See [eng/tools/BaselineGenerator/](/eng/tools/BaselineGenerator/README.md) for instructions on how to run this tool.
* **For packages with source code in this repo (not a submodule):** Update the list of packages in [eng/PatchConfig.props](/eng/PatchConfig.props) to list which packages should be patching in this release.
* **For packages still building from submodules:** Update the list of repositories which will contain changes in [build/submodules.props](/build/submodules.props).
* `<ShippedRepository>` items represent repos which were released in a previous patch, and will not contain servicing updates in the next patch.
* `<Repository>` items represent repos which will produce new packages in this patch.
* It is usually best to move everything to `<ShippedRepository>` and then iteratively add them back to `<Repository>` as new repos receive approval to patch.
* Don't change the `PatchPolicy` attribute. The build system uses this to ensure patching rules are obeyed.
* For each repository still listed as a `<Repository>`, update the version.props file in that submodule. For example, https://github.com/aspnet/Templating/pull/824
* The version prefix in repos should match the version of ASP.NET Core.
* Exception: SignalR, which is "1.1", not "2.1".
* This leaves holes in versioning, which is okay. This may mean you increment the patch value by more than one. Example:
* EF Core ships patches in 2.1.4 as "2.1.4"
* EF Core does not ship patches in 2.1.5 or 2.1.6
* EF Core ships in 2.1.7, therefore, EFCore's version.props file should jump from 2.1.4 to 2.1.7.
```diff
<!-- Example change to modules/EntityFrameworkCore/version.props -->
- <VersionPrefix>2.1.4</VersionPrefix>
+ <VersionPrefix>2.1.7</VersionPrefix>
```

116
eng/Baseline.props Normal file
View File

@ -0,0 +1,116 @@
<!-- Auto generated. Do not edit manually, use eng/tools/BaselineGenerator/ to recreate. -->
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<AspNetCoreBaselineVersion>2.2.0</AspNetCoreBaselineVersion>
</PropertyGroup>
<!-- Package: Microsoft.AspNetCore.Cryptography.Internal-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.Internal' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.Internal' AND '$(TargetFramework)' == 'netstandard2.0' " />
<!-- Package: Microsoft.AspNetCore.Cryptography.KeyDerivation-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.KeyDerivation' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.KeyDerivation' AND '$(TargetFramework)' == 'netcoreapp2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[2.2.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.KeyDerivation' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[2.2.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Win32.Registry" Version="[4.5.0, )" />
<BaselinePackageReference Include="System.Security.Cryptography.Xml" Version="[4.5.0, )" />
<BaselinePackageReference Include="System.Security.Principal.Windows" Version="[4.5.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.Abstractions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Abstractions' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' " />
<!-- Package: Microsoft.AspNetCore.DataProtection.AzureKeyVault-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureKeyVault' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureKeyVault' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Azure.KeyVault" Version="[2.3.2, )" />
<BaselinePackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="[3.19.8, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.AzureStorage-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
<BaselinePackageReference Include="WindowsAzure.Storage" Version="[8.1.4, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.EntityFrameworkCore-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.EntityFrameworkCore' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.EntityFrameworkCore' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore" Version="[2.2.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.Extensions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Extensions' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Extensions' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.StackExchangeRedis-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.StackExchangeRedis' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.StackExchangeRedis' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
<BaselinePackageReference Include="StackExchange.Redis" Version="[2.0.513, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.SystemWeb-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.SystemWeb' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.SystemWeb' AND '$(TargetFramework)' == 'net461' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Html.Abstractions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Html.Abstractions' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Html.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="System.Text.Encodings.Web" Version="[4.5.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.JsonPatch-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.CSharp" Version="[4.5.0, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[11.0.2, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.WebSockets-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.WebSockets' ">
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.WebSockets' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[2.2.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
<BaselinePackageReference Include="System.Net.WebSockets.WebSocketProtocol" Version="[4.5.1, )" />
</ItemGroup>
</Project>

72
eng/Dependencies.props Normal file
View File

@ -0,0 +1,72 @@
<!-- This file is a work in progress as we merge repos and move content here from build/dependencies.props. -->
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<Import Project="dependencies.temp.props" />
<ItemGroup Label="ProdCon dependencies">
<!-- These dependencies must use version variables because they may be overriden by ProdCon builds. -->
<LatestPackageReference Include="Microsoft.AspNetCore.Certificates.Generation.Sources" Version="$(MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
<LatestPackageReference Include="Microsoft.CSharp" Version="$(MicrosoftCSharpPackageVersion)" />
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(MicrosoftEntityFrameworkCoreInMemoryPackageVersion)" />
<LatestPackageReference Include="Microsoft.EntityFrameworkCore" Version="$(MicrosoftEntityFrameworkCorePackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.CommandLineUtils.Sources" Version="$(MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(MicrosoftExtensionsConfigurationCommandLinePackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsConfigurationJsonPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="$(MicrosoftExtensionsConfigurationUserSecretsPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsConfigurationPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsOptionsPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.Process.Sources" Version="$(MicrosoftExtensionsProcessSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.WebEncoders.Sources" Version="$(MicrosoftExtensionsWebEncodersSourcesPackageVersion)" />
<LatestPackageReference Include="Microsoft.Extensions.WebEncoders" Version="$(MicrosoftExtensionsWebEncodersPackageVersion)" />
<LatestPackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="$(MicrosoftIdentityModelClientsActiveDirectoryPackageVersion)" />
<LatestPackageReference Include="Microsoft.Win32.Registry" Version="$(MicrosoftWin32RegistryPackageVersion)" />
<LatestPackageReference Include="System.Data.SqlClient" Version="$(SystemDataSqlClientPackageVersion)" />
<LatestPackageReference Include="System.Net.WebSockets.WebSocketProtocol" Version="$(SystemNetWebSocketsWebSocketProtocolPackageVersion)" />
<LatestPackageReference Include="System.Security.Cryptography.Cng" Version="$(SystemSecurityCryptographyCngPackageVersion)" />
<LatestPackageReference Include="System.Security.Cryptography.Xml" Version="$(SystemSecurityCryptographyXmlPackageVersion)" />
<LatestPackageReference Include="System.Security.Principal.Windows" Version="$(SystemSecurityPrincipalWindowsPackageVersion)" />
<LatestPackageReference Include="System.Text.Encodings.Web" Version="$(SystemTextEncodingsWebPackageVersion)" />
</ItemGroup>
<ItemGroup Label="External dependencies">
<LatestPackageReference Include="Microsoft.Azure.KeyVault" Version="2.3.2" />
<LatestPackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<LatestPackageReference Include="Moq" Version="4.10.0" />
<!-- This version is required by MSBuild tasks or Visual Studio extensions. -->
<LatestPackageReference Include="Newtonsoft.Json" Version="9.0.1" Condition="'$(UseMSBuildJsonNet)' == 'true'" />
<!-- This version should be used by runtime packages -->
<LatestPackageReference Include="Newtonsoft.Json" Version="11.0.2" Condition="'$(UseMSBuildJsonNet)' != 'true'" />
<LatestPackageReference Include="StackExchange.Redis" Version="2.0.513" />
<LatestPackageReference Include="WindowsAzure.Storage" Version="8.1.4" />
<LatestPackageReference Include="xunit.abstractions" Version="2.0.1" />
<LatestPackageReference Include="xunit.analyzers" Version="0.10.0" />
<LatestPackageReference Include="xunit.assert" Version="2.3.1" />
<LatestPackageReference Include="xunit.extensibility.core" Version="2.3.1" />
<LatestPackageReference Include="xunit.extensibility.execution" Version="2.3.1" />
<LatestPackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<LatestPackageReference Include="xunit" Version="2.4.0" />
</ItemGroup>
<ItemGroup Condition=" '$(AddImplicitReferences)' != 'false' AND '$(IsTestProject)' == 'true' AND '$(MSBuildProjectExtension)' == '.csproj' ">
<Reference Include="Microsoft.AspNetCore.Testing" />
<Reference Include="Microsoft.NET.Test.Sdk" />
<Reference Include="Moq" />
<Reference Include="xunit" />
<Reference Include="xunit.analyzers" />
<Reference Include="xunit.runner.visualstudio" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,41 @@
{
"adx": {
"rules": [
"AdxVerificationCompositeRule"
],
"packages": {
"dotnet-watch": {
"packageTypes": [
"DotnetTool"
]
},
"dotnet-sql-cache": {
"packageTypes": [
"DotnetTool"
]
},
"dotnet-user-secrets": {
"packageTypes": [
"DotnetTool"
]
},
"dotnet-dev-certs": {
"packageTypes": [
"DotnetTool"
]
},
"Microsoft.AspNetCore.DeveloperCertificates.XPlat": {
"Exclusions": {
"DOC_MISSING": {
"lib/netcoreapp3.0/Microsoft.AspNetCore.DeveloperCertificates.XPlat.dll": "Docs not required to shipoob package"
}
}
}
}
},
"Default": {
"rules": [
"DefaultCompositeRule"
]
}
}

14
eng/PatchConfig.props Normal file
View File

@ -0,0 +1,14 @@
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.1' ">
<PackagesInPatch>
Microsoft.AspNetCore.Server.IIS;
Microsoft.AspNetCore.Server.IISIntegration;
Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
</PackagesInPatch>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,23 @@
<!-- This file is automatically generated. Run `build.cmd /t:GenerateProjectList` to update. -->
<Project>
<ItemGroup>
<ProjectReferenceProvider Include="Microsoft.AspNetCore.JsonPatch" ProjectPath="$(RepositoryRoot)src\Features\JsonPatch\src\Microsoft.AspNetCore.JsonPatch.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.Abstractions" ProjectPath="$(RepositoryRoot)src\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.AzureKeyVault" ProjectPath="$(RepositoryRoot)src\DataProtection\AzureKeyVault\src\Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.AzureStorage" ProjectPath="$(RepositoryRoot)src\DataProtection\AzureStorage\src\Microsoft.AspNetCore.DataProtection.AzureStorage.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cryptography.Internal" ProjectPath="$(RepositoryRoot)src\DataProtection\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" ProjectPath="$(RepositoryRoot)src\DataProtection\Cryptography.KeyDerivation\src\Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection" ProjectPath="$(RepositoryRoot)src\DataProtection\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" ProjectPath="$(RepositoryRoot)src\DataProtection\EntityFrameworkCore\src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.Extensions" ProjectPath="$(RepositoryRoot)src\DataProtection\Extensions\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" ProjectPath="$(RepositoryRoot)src\DataProtection\StackExchangeRedis\src\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.SystemWeb" ProjectPath="$(RepositoryRoot)src\DataProtection\SystemWeb\src\Microsoft.AspNetCore.DataProtection.SystemWeb.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Html.Abstractions" ProjectPath="$(RepositoryRoot)src\Html\Abstractions\src\Microsoft.AspNetCore.Html.Abstractions.csproj" />
<ProjectReferenceProvider Include="dotnet-dev-certs" ProjectPath="$(RepositoryRoot)src\Tools\dotnet-dev-certs\src\dotnet-dev-certs.csproj" />
<ProjectReferenceProvider Include="dotnet-sql-cache" ProjectPath="$(RepositoryRoot)src\Tools\dotnet-sql-cache\src\dotnet-sql-cache.csproj" />
<ProjectReferenceProvider Include="dotnet-user-secrets" ProjectPath="$(RepositoryRoot)src\Tools\dotnet-user-secrets\src\dotnet-user-secrets.csproj" />
<ProjectReferenceProvider Include="dotnet-watch" ProjectPath="$(RepositoryRoot)src\Tools\dotnet-watch\src\dotnet-watch.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DeveloperCertificates.XPlat" ProjectPath="$(RepositoryRoot)src\Tools\FirstRunCertGenerator\src\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.WebSockets" ProjectPath="$(RepositoryRoot)src\Middleware\WebSockets\src\Microsoft.AspNetCore.WebSockets.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,17 @@
<!--
This file is temporary until aspnet/Hosting, Diagnostics, StaticFiles, and HttpAbstractions are merged into this repo.
This is required to provide dependencies for samples and tests.
-->
<Project>
<ItemGroup>
<LatestPackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Hosting" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Http.Features" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="3.0.0-alpha1-10717" />
<LatestPackageReference Include="Microsoft.AspNetCore.Http" Version="3.0.0-alpha1-10717" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,14 @@
<Project>
<PropertyGroup>
<LangVersion>7.2</LangVersion>
<!-- Instructs the compiler to use SHA256 instead of SHA1 when adding file hashes to PDBs. -->
<ChecksumAlgorithm>SHA256</ChecksumAlgorithm>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,5 @@
<Project>
<Import Project="Packaging.targets" />
<Import Project="ResolveReferences.targets" />
</Project>

View File

@ -0,0 +1,30 @@
<Project>
<Target Name="EnsureBaselineIsUpdated"
Condition="'$(IsServicingBuild)' == 'true' AND '$(AspNetCoreBaselineVersion)' != '$(PreviousAspNetCoreReleaseVersion)'"
BeforeTargets="BeforeBuild">
<Error Text="The package baseline ($(AspNetCoreBaselineVersion)) is out of date with the latest release of this repo ($(PreviousAspNetCoreReleaseVersion)).
See $(RepositoryRoot)eng\tools\BaselineGenerator\README.md for instructions on updating this baseline." />
</Target>
<!-- Temporary: this target is used to gather version information to pass to submodule builds. This can be removed after we finish merging submodules. -->
<Target Name="GetBaselineArtifactInfo"
Condition="'$(IsPackableInNonServicingBuild)' == 'true' AND '$(IsSubfolderBuild)' != 'true' "
Returns="@(ArtifactInfo)"
BeforeTargets="GetArtifactInfo">
<PropertyGroup>
<FullPackageOutputPath>$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg</FullPackageOutputPath>
</PropertyGroup>
<ItemGroup>
<ArtifactInfo Include="$(FullPackageOutputPath)">
<ArtifactType>NuGetPackage</ArtifactType>
<PackageId>$(PackageId)</PackageId>
<Version>$(PackageVersion)</Version>
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
<IsShipped>true</IsShipped>
</ArtifactInfo>
</ItemGroup>
</Target>
</Project>

View File

@ -0,0 +1,135 @@
<Project>
<PropertyGroup>
<ResolveReferencesDependsOn>
ResolveCustomReferences;
$(ResolveReferencesDependsOn);
</ResolveReferencesDependsOn>
</PropertyGroup>
<PropertyGroup>
<!--
Projects should only use the latest package references when:
* preparing a new major or minor release (i.e. a non-servicing builds)
* when a project is a test or sample project
* when a package is releasing a new patch (we like to update external dependencies in patches when possible)
-->
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsServicingBuild)' != 'true' ">true</UseLatestPackageReferences>
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsImplementationProject)' != 'true' ">true</UseLatestPackageReferences>
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsImplementationProject)' == 'true' AND ( '$(IsServicingBuild)' != 'true' OR '$(IsPackable)' == 'true' ) ">true</UseLatestPackageReferences>
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' ">false</UseLatestPackageReferences>
<!--
Projects should only use the project references instead of baseline package references when:
* preparing a new major or minor release (i.e. a non-servicing builds)
* when a project is a test or sample project
We don't use project references between components in servicing builds between compontents to preserve the baseline as much as possible.
-->
<UseProjectReferences Condition=" '$(UseProjectReferences)' == '' AND '$(IsServicingBuild)' != 'true' ">true</UseProjectReferences>
<UseProjectReferences Condition=" '$(UseProjectReferences)' == '' AND '$(IsImplementationProject)' != 'true' ">true</UseProjectReferences>
<UseProjectReferences Condition=" '$(UseProjectReferences)' == '' ">false</UseProjectReferences>
</PropertyGroup>
<ItemGroup>
<_ImplicitPackageReference Include="@(PackageReference->WithMetadataValue('IsImplicitlyDefined', 'true'))" />
<_ExplicitPackageReference Include="@(PackageReference)" Exclude="@(_ImplicitPackageReference)" />
<_ExplicitPackageReference Remove="Internal.AspNetCore.Sdk" />
<UnusedProjectReferenceProvider Include="@(ProjectReferenceProvider)" Exclude="@(Reference)" />
<!-- Order matters. Projects should be used when possible instead of packages. -->
<_ProjectReferenceByAssemblyName Condition="'$(UseProjectReferences)' == 'true'"
Include="@(ProjectReferenceProvider)"
Exclude="@(UnusedProjectReferenceProvider)" />
<ProjectReference Include="@(_ProjectReferenceByAssemblyName->'%(ProjectPath)')" />
<Reference Remove="@(_ProjectReferenceByAssemblyName)" />
</ItemGroup>
<Target Name="ResolveCustomReferences" BeforeTargets="CollectPackageReferences;ResolveAssemblyReferencesDesignTime;ResolveAssemblyReferences" Condition=" '$(TargetFramework)' != '' ">
<ItemGroup>
<UnusedBaselinePackageReference Include="@(BaselinePackageReference)" Exclude="@(Reference);@(_ProjectReferenceByAssemblyName)" />
<!--
MSBuild does not provide a way to join on matching identities in a Condition,
but you can do a cartesian product of two item groups and filter out mismatched id's in a second pass.
-->
<_LatestPackageReferenceWithVersion Include="@(Reference)" Condition=" '$(UseLatestPackageReferences)' == 'true' ">
<Id>%(LatestPackageReference.Identity)</Id>
<Version>%(LatestPackageReference.Version)</Version>
</_LatestPackageReferenceWithVersion>
<_LatestPackageReferenceWithVersion Remove="@(_LatestPackageReferenceWithVersion)" Condition="'%(Id)' != '%(Identity)' " />
<!-- Remove reference items that have been resolved to a LatestPackageReference item. -->
<Reference Remove="@(_LatestPackageReferenceWithVersion)" />
<PackageReference Include="@(_LatestPackageReferenceWithVersion)" IsImplicitlyDefined="true" />
<!-- Resolve references from BaselinePackageReference for servicing builds. -->
<_BaselinePackageReferenceWithVersion Include="@(Reference)" Condition=" '$(IsServicingBuild)' == 'true' OR '$(UseLatestPackageReferences)' != 'true' ">
<Id>%(BaselinePackageReference.Identity)</Id>
<Version>%(BaselinePackageReference.Version)</Version>
</_BaselinePackageReferenceWithVersion>
<_BaselinePackageReferenceWithVersion Remove="@(_BaselinePackageReferenceWithVersion)" Condition="'%(Id)' != '%(Identity)' " />
<!-- Remove reference items that have been resolved to a BaselinePackageReference item. -->
<PackageReference Include="@(_BaselinePackageReferenceWithVersion)" IsImplicitlyDefined="true" />
<Reference Remove="@(_BaselinePackageReferenceWithVersion)" />
<!-- For PrivateAssets=All references, like .Sources packages, fallback to LatestPackageReferences. -->
<_PrivatePackageReferenceWithVersion Include="@(Reference->WithMetadataValue('PrivateAssets', 'All'))">
<Id>%(LatestPackageReference.Identity)</Id>
<Version>%(LatestPackageReference.Version)</Version>
</_PrivatePackageReferenceWithVersion>
<_PrivatePackageReferenceWithVersion Remove="@(_PrivatePackageReferenceWithVersion)" Condition="'%(Id)' != '%(Identity)' " />
<!-- Remove reference items that have been resolved to a LatestPackageReference item. -->
<PackageReference Include="@(_PrivatePackageReferenceWithVersion)" IsImplicitlyDefined="true" />
<Reference Remove="@(_PrivatePackageReferenceWithVersion)" />
<!-- Free up memory for unnecessary items -->
<_LatestPackageReferenceWithVersion Remove="@(_LatestPackageReferenceWithVersion)" />
<_BaselinePackageReferenceWithVersion Remove="@(_BaselinePackageReferenceWithVersion)" />
<_PrivatePackageReferenceWithVersion Remove="@(_PrivatePackageReferenceWithVersion)" />
<_ImplicitPackageReference Remove="@(_ImplicitPackageReference)" />
</ItemGroup>
<!--
<Error Condition="@(_ExplicitPackageReference->Count()) != 0"
Text="PackageReference items are not allowed. Use &lt;Reference&gt; instead. " /> -->
<ItemGroup>
<_ExplicitPackageReference Remove="@(_ExplicitPackageReference)" />
</ItemGroup>
<Warning Condition="@(UnusedBaselinePackageReference->Count()) != 0"
Text="Package references changed since the last release. This could be a breaking change. References removed:%0A - @(UnusedBaselinePackageReference, '%0A -')" />
<Error Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework' AND '%(Reference.Identity)' != '' AND ! Exists('%(Reference.Identity)')"
Code="MSB3245"
Text="Could not resolve this reference. Could not locate the package or project for &quot;%(Reference.Identity)&quot;" />
</Target>
<Target Name="GetReferencesProvided" Returns="@(ProvidesReference)">
<ItemGroup>
<_TargetFramework Remove="@(_TargetFramework)" />
<_TargetFramework Include="$(TargetFramework)" Condition="'$(TargetFramework)' != '' "/>
<_TargetFramework Include="$(TargetFrameworks)" Condition="'$(TargetFramework)' == '' "/>
</ItemGroup>
<MSBuild Projects="$(MSBuildProjectFullPath)"
Targets="_GetReferencesProvided"
Properties="TargetFramework=%(_TargetFramework.Identity)">
<Output TaskParameter="TargetOutputs" ItemName="ProvidesReference" />
</MSBuild>
</Target>
<Target Name="_GetReferencesProvided" Returns="@(ProvidesReference)">
<ItemGroup Condition=" '$(IsImplementationProject)' == 'true' OR '$(IsProjectReferenceProvider)' == 'true' ">
<ProvidesReference Include="$(AssemblyName)">
<ProjectFileRelativePath>$([MSBuild]::MakeRelative($(RepositoryRoot), $(MSBuildProjectFullPath)))</ProjectFileRelativePath>
</ProvidesReference>
</ItemGroup>
</Target>
</Project>

View File

@ -332,4 +332,32 @@ This targets file should only be imported by .shfxproj files.
</Target>
<Target Name="CreateManifestResourceNames" />
<Target Name="GetArtifactInfo" Returns="@(ArtifactInfo)">
<PropertyGroup>
<FullPackageOutputPath>$(PackageOutputPath)$(PackageId).$(PackageVersion).nupkg</FullPackageOutputPath>
<SymbolsPackageOutputPath>$(PackageOutputPath)$(PackageId).$(PackageVersion).symbols.nupkg</SymbolsPackageOutputPath>
</PropertyGroup>
<ItemGroup>
<ArtifactInfo Include="$(FullPackageOutputPath)">
<ArtifactType>NuGetPackage</ArtifactType>
<PackageId>$(PackageId)</PackageId>
<Version>$(PackageVersion)</Version>
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
<Certificate>$(PackageSigningCertName)</Certificate>
<ShouldBeSigned>true</ShouldBeSigned>
<IsContainer>true</IsContainer>
</ArtifactInfo>
<ArtifactInfo Include="$(SymbolsPackageOutputPath)" Condition="'$(IncludeSymbols)' != 'false'">
<ArtifactType>NuGetSymbolsPackage</ArtifactType>
<PackageId>$(PackageId)</PackageId>
<Version>$(PackageVersion)</Version>
<RepositoryRoot>$(RepositoryRoot)</RepositoryRoot>
<Certificate>$(PackageSigningCertName)</Certificate>
<ShouldBeSigned>true</ShouldBeSigned>
<IsContainer>true</IsContainer>
</ArtifactInfo>
</ItemGroup>
</Target>
</Project>

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<StartArguments>-o "$(MSBuildThisFileDirectory)../../Baseline.props"</StartArguments>
<StartWorkingDirectory>$(MSBuildProjectDirectory)</StartWorkingDirectory>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NuGet.Packaging" Version="4.8.0" />
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,138 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Extensions.CommandLineUtils;
using NuGet.Packaging;
using NuGet.Packaging.Core;
namespace PackageBaselineGenerator
{
/// <summary>
/// This generates Baseline.props with information about the last RTM release.
/// </summary>
class Program : CommandLineApplication
{
static void Main(string[] args)
{
new Program().Execute(args);
}
private readonly CommandOption _source;
private readonly CommandOption _output;
private readonly CommandOption _feedv3;
public Program()
{
_source = Option("-s|--source <SOURCE>", "The NuGet v2 source of the package to fetch", CommandOptionType.SingleValue);
_output = Option("-o|--output <OUT>", "The generated file output path", CommandOptionType.SingleValue);
_feedv3 = Option("--v3", "Sources is nuget v3", CommandOptionType.NoValue);
Invoke = () => Run().GetAwaiter().GetResult();
}
private async Task<int> Run()
{
var source = _source.HasValue()
? _source.Value()
: "https://www.nuget.org/api/v2/package";
var packageCache = Environment.GetEnvironmentVariable("NUGET_PACKAGES") != null
? Environment.GetEnvironmentVariable("NUGET_PACKAGES")
: Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
var tempDir = Path.Combine(Directory.GetCurrentDirectory(), "obj", "tmp");
Directory.CreateDirectory(tempDir);
var input = XDocument.Load(Path.Combine(Directory.GetCurrentDirectory(), "baseline.xml"));
var output = _output.HasValue()
? _output.Value()
: Path.Combine(Directory.GetCurrentDirectory(), "Baseline.props");
var baselineVersion = input.Root.Attribute("Version").Value;
var doc = new XDocument(
new XComment(" Auto generated. Do not edit manually, use eng/tools/BaselineGenerator/ to recreate. "),
new XElement("Project",
new XElement("PropertyGroup",
new XElement("MSBuildAllProjects", "$(MSBuildAllProjects);$(MSBuildThisFileFullPath)"),
new XElement("AspNetCoreBaselineVersion", baselineVersion))));
var client = new HttpClient();
foreach (var pkg in input.Root.Descendants("Package"))
{
var id = pkg.Attribute("Id").Value;
var version = pkg.Attribute("Version").Value;
var packageFileName = $"{id}.{version}.nupkg";
var nupkgPath = Path.Combine(packageCache, id.ToLowerInvariant(), version, packageFileName);
if (!File.Exists(nupkgPath))
{
nupkgPath = Path.Combine(tempDir, packageFileName);
}
if (!File.Exists(nupkgPath))
{
var url = _feedv3.HasValue()
? $"{source}/{id.ToLowerInvariant()}/{version}/{id.ToLowerInvariant()}.{version}.nupkg"
: $"{source}/{id}/{version}";
Console.WriteLine($"Downloading {url}");
var response = await client.GetStreamAsync(url);
using (var file = File.Create(nupkgPath))
{
await response.CopyToAsync(file);
}
}
using (var reader = new PackageArchiveReader(nupkgPath))
{
var first = true;
foreach (var group in reader.NuspecReader.GetDependencyGroups())
{
if (first)
{
first = false;
doc.Root.Add(new XComment($" Package: {id}"));
var propertyGroup = new XElement("PropertyGroup",
new XAttribute("Condition", $" '$(PackageId)' == '{id}' "),
new XElement("BaselinePackageVersion", version));
doc.Root.Add(propertyGroup);
}
var itemGroup = new XElement("ItemGroup", new XAttribute("Condition", $" '$(PackageId)' == '{id}' AND '$(TargetFramework)' == '{group.TargetFramework.GetShortFolderName()}' "));
doc.Root.Add(itemGroup);
foreach (var dependency in group.Packages)
{
itemGroup.Add(new XElement("BaselinePackageReference", new XAttribute("Include", dependency.Id), new XAttribute("Version", dependency.VersionRange.ToString())));
}
}
}
}
var settings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8,
Indent = true,
};
using (var writer = XmlWriter.Create(output, settings))
{
doc.Save(writer);
}
return 0;
}
}
}

View File

@ -0,0 +1,10 @@
BaselineGenerator
=================
This tool is used to generate an MSBuild file which sets the "baseline" against which servicing updates are built.
## Usage
1. Add to the [baseline.xml](./baseline.xml) a list of package ID's and their latest released versions. The source of this information can typically
be found in the build.xml file generated during ProdCon builds. See https://github.com/dotnet/versions/blob/master/build-info/dotnet/product/cli/release/2.1.6/build.xml for example.
2. Run `dotnet run` on this project.

View File

@ -0,0 +1,19 @@
<Baseline Version="2.2.0">
<Package Id="dotnet-dev-certs" Version="2.2.0" />
<Package Id="dotnet-sql-cache" Version="2.2.0" />
<Package Id="dotnet-user-secrets" Version="2.2.0" />
<Package Id="dotnet-watch" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.Internal" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.SystemWeb" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.JsonPatch" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.WebSockets" Version="2.2.0" />
</Baseline>

View File

@ -0,0 +1,3 @@
<Project>
<Import Project="..\..\build\sources.props" />
</Project>

View File

@ -0,0 +1,2 @@
<Project>
</Project>

34
eng/tools/tools.sln Normal file
View File

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaselineGenerator", "BaselineGenerator\BaselineGenerator.csproj", "{CF76A947-3A72-4824-87E6-BF029D84218B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x64.ActiveCfg = Debug|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x64.Build.0 = Debug|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x86.ActiveCfg = Debug|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Debug|x86.Build.0 = Debug|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Release|Any CPU.Build.0 = Release|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x64.ActiveCfg = Release|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x64.Build.0 = Release|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x86.ActiveCfg = Release|Any CPU
{CF76A947-3A72-4824-87E6-BF029D84218B}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -3,6 +3,6 @@
"version": "3.0.100-preview-009750"
},
"msbuild-sdks": {
"Internal.AspNetCore.Sdk": "3.0.0-alpha1-20181114.4"
"Internal.AspNetCore.Sdk": "3.0.0-build-20181114.5"
}
}

View File

@ -1,2 +1,2 @@
version:3.0.0-alpha1-20181114.4
commithash:576bd9858150e9aec1c3527dc68ebe9f69d55b5a
version:3.0.0-build-20181114.5
commithash:880e9a204d4ee4a18dfd83c9fb05a192a28bca60

@ -1 +0,0 @@
Subproject commit a24b4ee4598b425d9e8b2f041be508c32eb41cf5

@ -1 +0,0 @@
Subproject commit 45b7e2ddb796f0cb909d8f04bc4b5a5cf13b5e46

@ -1 +0,0 @@
Subproject commit bf9fd0d10667e605d1df45f89e198be7f3bd1138

View File

@ -56,7 +56,6 @@ foreach ($package in $remoteDeps.SelectNodes('//Package')) {
if (-not $NoCommit) {
$currentBranch = Invoke-Block { & git rev-parse --abbrev-ref HEAD }
$destinationBranch = "dotnetbot/UpdateDeps"
Invoke-Block { & git checkout -tb $destinationBranch "origin/$GithubUpstreamBranch" }
}

View File

@ -15,7 +15,7 @@ Microsoft.AspNetCore.DataProtection.IDataProtector</Description>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.WebEncoders.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsWebEncodersSourcesPackageVersion)" />
<Reference Include="Microsoft.Extensions.WebEncoders.Sources" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -5,8 +5,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Abstractions" />
</ItemGroup>
</Project>

View File

@ -9,12 +9,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="$(MicrosoftIdentityModelClientsActiveDirectoryPackageVersion)" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="$(MicrosoftAzureKeyVaultPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.Azure.KeyVault" />
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" />
</ItemGroup>
</Project>

View File

@ -6,12 +6,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.AspNetCore.DataProtection.AzureKeyVault" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

@ -9,11 +9,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="WindowsAzure.Storage" Version="$(WindowsAzureStoragePackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="WindowsAzure.Storage" />
</ItemGroup>
</Project>

View File

@ -6,12 +6,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.AzureStorage.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.AspNetCore.DataProtection.AzureStorage" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

@ -10,7 +10,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
</ItemGroup>
</Project>

View File

@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
</ItemGroup>
</Project>

View File

@ -10,8 +10,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
<ProjectReference Include="..\src\Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
<Reference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" />
</ItemGroup>
</Project>

View File

@ -14,18 +14,15 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
<ProjectReference Include="..\..\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsOptionsPackageVersion)" />
<PackageReference Include="Microsoft.Win32.Registry" Version="$(MicrosoftWin32RegistryPackageVersion)" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="$(SystemSecurityCryptographyXmlPackageVersion)" />
<PackageReference Include="System.Security.Principal.Windows" Version="$(SystemSecurityPrincipalWindowsPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
<Reference Include="Microsoft.Extensions.Options" />
<Reference Include="Microsoft.Win32.Registry" />
<Reference Include="System.Security.Cryptography.Xml" />
<Reference Include="System.Security.Principal.Windows" />
</ItemGroup>
</Project>

View File

@ -11,12 +11,12 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<!-- TODO replace all PackageReference with ProjectReference once aspnet/Hosting has merged to this repo -->
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.1.1" />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

@ -1,24 +0,0 @@
<Project>
<PropertyGroup>
<!-- Temporary until we can replace PackageRef with ProjectRef -->
<SubFolderRepoBuild>true</SubFolderRepoBuild>
</PropertyGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
<Import Project="version.props" />
<ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(IsTestProject)' == 'true' ">
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
<PackageReference Include="Moq" Version="$(MoqPackageVersion)" />
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualStudioPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -9,15 +9,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="$(MicrosoftEntityFrameworkCorePackageVersion)" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.EntityFrameworkCore" />
</ItemGroup>
</Project>

View File

@ -5,11 +5,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(MicrosoftEntityFrameworkCoreInMemoryPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj" />
<Reference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" />
<Reference Include="Microsoft.EntityFrameworkCore.InMemory" />
</ItemGroup>
</Project>

View File

@ -12,11 +12,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

@ -10,8 +10,9 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
<Reference Include="Microsoft.AspNetCore.Cryptography.Internal" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Abstractions" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Extensions" />
</ItemGroup>
</Project>

View File

@ -9,11 +9,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StackExchange.Redis" Version="$(StackExchangeRedisPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="StackExchange.Redis" />
</ItemGroup>
</Project>

View File

@ -11,14 +11,11 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
<ProjectReference Include="..\src\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsConfigurationJsonPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="$(MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Abstractions" />
<Reference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" />
<Reference Include="Microsoft.Extensions.Configuration.Json" />
<Reference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
</Project>

View File

@ -13,11 +13,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web" />
</ItemGroup>

View File

@ -1,12 +0,0 @@
<Project>
<Import Project="..\..\..\build\dependencies.props" />
<Import Project="..\..\..\build\runtimes.props" />
<PropertyGroup>
<!-- TODO: temporary while we reorganize source code and refactor dependency management -->
<DisablePackageReferenceRestrictions>true</DisablePackageReferenceRestrictions>
<OverridePackageOutputPath>false</OverridePackageOutputPath>
<BuildSolutions>false</BuildSolutions>
<DataProtectionRoot>$([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)..\'))</DataProtectionRoot>
<Projects>$(DataProtectionRoot)**\*.csproj</Projects>
</PropertyGroup>
</Project>

View File

@ -6,14 +6,11 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
<ProjectReference Include="..\..\AzureStorage\src\Microsoft.AspNetCore.DataProtection.AzureStorage.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.AspNetCore.DataProtection.AzureStorage" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>
</Project>

View File

@ -6,15 +6,12 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\AzureKeyVault\src\Microsoft.AspNetCore.DataProtection.AzureKeyVault.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsConfigurationPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsConfigurationJsonPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection.AzureKeyVault" />
<Reference Include="Microsoft.Extensions.Configuration" />
<Reference Include="Microsoft.Extensions.Configuration.Json" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>
</Project>

View File

@ -6,13 +6,10 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
<ProjectReference Include="..\..\Extensions\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Extensions" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>
</Project>

View File

@ -6,8 +6,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
<ProjectReference Include="..\..\Extensions\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
<Reference Include="Microsoft.AspNetCore.DataProtection" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Extensions" />
</ItemGroup>
</Project>

View File

@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Extensions\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
<Reference Include="Microsoft.AspNetCore.DataProtection.Extensions" />
</ItemGroup>
</Project>

View File

@ -6,13 +6,10 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\StackExchangeRedis\src\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<Reference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" />
<Reference Include="Microsoft.Extensions.DependencyInjection" />
<Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>
</Project>

View File

@ -1,10 +0,0 @@
<Project>
<PropertyGroup>
<VersionPrefix>3.0.0</VersionPrefix>
<VersionSuffix>alpha1</VersionSuffix>
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
<BuildNumber Condition="'$(BuildNumber)' == ''">t000</BuildNumber>
<VersionSuffix Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,49 @@
using Microsoft.AspNetCore.JsonPatch.Internal;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.AspNetCore.JsonPatch.Adapters
{
/// <summary>
/// The default AdapterFactory to be used for resolving <see cref="IAdapter"/>.
/// </summary>
public class AdapterFactory : IAdapterFactory
{
/// <inheritdoc />
public virtual IAdapter Create(object target, IContractResolver contractResolver)
{
if (target == null)
{
throw new ArgumentNullException(nameof(target));
}
if (contractResolver == null)
{
throw new ArgumentNullException(nameof(contractResolver));
}
var jsonContract = contractResolver.ResolveContract(target.GetType());
if (target is IList)
{
return new ListAdapter();
}
else if (jsonContract is JsonDictionaryContract jsonDictionaryContract)
{
var type = typeof(DictionaryAdapter<,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType);
return (IAdapter)Activator.CreateInstance(type);
}
else if (jsonContract is JsonDynamicContract)
{
return new DynamicObjectAdapter();
}
else
{
return new PocoAdapter();
}
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.JsonPatch.Internal;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.AspNetCore.JsonPatch.Adapters
{
/// <summary>
/// Defines the operations used for loading an <see cref="IAdapter"/> based on the current object and ContractResolver.
/// </summary>
public interface IAdapterFactory
{
/// <summary>
/// Creates an <see cref="IAdapter"/> for the current object
/// </summary>
/// <param name="target">The target object</param>
/// <param name="contractResolver">The current contract resolver</param>
/// <returns>The needed <see cref="IAdapter"/></returns>
IAdapter Create(object target, IContractResolver contractResolver);
}
}

View File

@ -0,0 +1,112 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.JsonPatch.Operations;
namespace Microsoft.AspNetCore.JsonPatch.Adapters
{
/// <summary>
/// Defines the operations that can be performed on a JSON patch document.
/// </summary>
public interface IObjectAdapter
{
/// <summary>
/// Using the "add" operation a new value is inserted into the root of the target
/// document, into the target array at the specified valid index, or to a target object at
/// the specified location.
///
/// When adding to arrays, the specified index MUST NOT be greater than the number of elements in the array.
/// To append the value to the array, the index of "-" character is used (see [RFC6901]).
///
/// When adding to an object, if an object member does not already exist, a new member is added to the object at the
/// specified location or if an object member does exist, that member's value is replaced.
///
/// The operation object MUST contain a "value" member whose content
/// specifies the value to be added.
///
/// For example:
///
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
///
/// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-4
/// </summary>
/// <param name="operation">The add operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Add(Operation operation, object objectToApplyTo);
/// <summary>
/// Using the "copy" operation, a value is copied from a specified location to the
/// target location.
///
/// The operation object MUST contain a "from" member, which references the location in the
/// target document to copy the value from.
///
/// The "from" location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
///
/// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-7
/// </summary>
/// <param name="operation">The copy operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Copy(Operation operation, object objectToApplyTo);
/// <summary>
/// Using the "move" operation the value at a specified location is removed and
/// added to the target location.
///
/// The operation object MUST contain a "from" member, which references the location in the
/// target document to move the value from.
///
/// The "from" location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
///
/// A location cannot be moved into one of its children.
///
/// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-6
/// </summary>
/// <param name="operation">The move operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Move(Operation operation, object objectToApplyTo);
/// <summary>
/// Using the "remove" operation the value at the target location is removed.
///
/// The target location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "remove", "path": "/a/b/c" }
///
/// If removing an element from an array, any elements above the
/// specified index are shifted one position to the left.
///
/// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-6
/// </summary>
/// <param name="operation">The remove operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Remove(Operation operation, object objectToApplyTo);
/// <summary>
/// Using the "replace" operation he value at the target location is replaced
/// with a new value. The operation object MUST contain a "value" member
/// which specifies the replacement value.
///
/// The target location MUST exist for the operation to be successful.
///
/// For example:
///
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
///
/// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-6
/// </summary>
/// <param name="operation">The replace operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Replace(Operation operation, object objectToApplyTo);
}
}

View File

@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.JsonPatch.Operations;
namespace Microsoft.AspNetCore.JsonPatch.Adapters
{
/// <summary>
/// Defines the operations that can be performed on a JSON patch document, including "test".
/// </summary>
public interface IObjectAdapterWithTest : IObjectAdapter
{
/// <summary>
/// Using the "test" operation a value at the target location is compared for
/// equality to a specified value.
///
/// The operation object MUST contain a "value" member that specifies
/// value to be compared to the target location's value.
///
/// The target location MUST be equal to the "value" value for the
/// operation to be considered successful.
///
/// For example:
/// { "op": "test", "path": "/a/b/c", "value": "foo" }
///
/// See RFC 6902 https://tools.ietf.org/html/rfc6902#page-7
/// </summary>
/// <param name="operation">The test operation.</param>
/// <param name="objectToApplyTo">Object to apply the operation to.</param>
void Test(Operation operation, object objectToApplyTo);
}
}

View File

@ -0,0 +1,348 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Internal;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Adapters
{
/// <inheritdoc />
public class ObjectAdapter : IObjectAdapterWithTest
{
/// <summary>
/// Initializes a new instance of <see cref="ObjectAdapter"/>.
/// </summary>
/// <param name="contractResolver">The <see cref="IContractResolver"/>.</param>
/// <param name="logErrorAction">The <see cref="Action"/> for logging <see cref="JsonPatchError"/>.</param>
public ObjectAdapter(
IContractResolver contractResolver,
Action<JsonPatchError> logErrorAction):
this(contractResolver, logErrorAction, new AdapterFactory())
{
}
/// <summary>
/// Initializes a new instance of <see cref="ObjectAdapter"/>.
/// </summary>
/// <param name="contractResolver">The <see cref="IContractResolver"/>.</param>
/// <param name="logErrorAction">The <see cref="Action"/> for logging <see cref="JsonPatchError"/>.</param>
/// <param name="adapterFactory">The <see cref="IAdapterFactory"/> to use when creating adaptors.</param>
public ObjectAdapter(
IContractResolver contractResolver,
Action<JsonPatchError> logErrorAction,
IAdapterFactory adapterFactory)
{
ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
LogErrorAction = logErrorAction;
AdapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory));
}
/// <summary>
/// Gets or sets the <see cref="IContractResolver"/>.
/// </summary>
public IContractResolver ContractResolver { get; }
/// <summary>
/// Gets or sets the <see cref="IAdapterFactory"/>
/// </summary>
public IAdapterFactory AdapterFactory { get; }
/// <summary>
/// Action for logging <see cref="JsonPatchError"/>.
/// </summary>
public Action<JsonPatchError> LogErrorAction { get; }
public void Add(Operation operation, object objectToApplyTo)
{
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
Add(operation.path, operation.value, objectToApplyTo, operation);
}
/// <summary>
/// Add is used by various operations (eg: add, copy, ...), yet through different operations;
/// This method allows code reuse yet reporting the correct operation on error
/// </summary>
private void Add(
string path,
object value,
object objectToApplyTo,
Operation operation)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
var parsedPath = new ParsedPath(path);
var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory);
var target = objectToApplyTo;
if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage))
{
var error = CreatePathNotFoundError(objectToApplyTo, path, operation, errorMessage);
ErrorReporter(error);
return;
}
if (!adapter.TryAdd(target, parsedPath.LastSegment, ContractResolver, value, out errorMessage))
{
var error = CreateOperationFailedError(objectToApplyTo, path, operation, errorMessage);
ErrorReporter(error);
return;
}
}
public void Move(Operation operation, object objectToApplyTo)
{
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
// Get value at 'from' location and add that value to the 'path' location
if (TryGetValue(operation.from, objectToApplyTo, operation, out var propertyValue))
{
// remove that value
Remove(operation.from, objectToApplyTo, operation);
// add that value to the path location
Add(operation.path,
propertyValue,
objectToApplyTo,
operation);
}
}
public void Remove(Operation operation, object objectToApplyTo)
{
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
Remove(operation.path, objectToApplyTo, operation);
}
/// <summary>
/// Remove is used by various operations (eg: remove, move, ...), yet through different operations;
/// This method allows code reuse yet reporting the correct operation on error. The return value
/// contains the type of the item that has been removed (and a bool possibly signifying an error)
/// This can be used by other methods, like replace, to ensure that we can pass in the correctly
/// typed value to whatever method follows.
/// </summary>
private void Remove(string path, object objectToApplyTo, Operation operationToReport)
{
var parsedPath = new ParsedPath(path);
var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory);
var target = objectToApplyTo;
if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage))
{
var error = CreatePathNotFoundError(objectToApplyTo, path, operationToReport, errorMessage);
ErrorReporter(error);
return;
}
if (!adapter.TryRemove(target, parsedPath.LastSegment, ContractResolver, out errorMessage))
{
var error = CreateOperationFailedError(objectToApplyTo, path, operationToReport, errorMessage);
ErrorReporter(error);
return;
}
}
public void Replace(Operation operation, object objectToApplyTo)
{
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
var parsedPath = new ParsedPath(operation.path);
var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory);
var target = objectToApplyTo;
if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage))
{
var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage);
ErrorReporter(error);
return;
}
if (!adapter.TryReplace(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage))
{
var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage);
ErrorReporter(error);
return;
}
}
public void Copy(Operation operation, object objectToApplyTo)
{
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
// Get value at 'from' location and add that value to the 'path' location
if (TryGetValue(operation.from, objectToApplyTo, operation, out var propertyValue))
{
// Create deep copy
var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue?.GetType());
if (copyResult.CanBeConverted)
{
Add(operation.path,
copyResult.ConvertedInstance,
objectToApplyTo,
operation);
}
else
{
var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, Resources.FormatCannotCopyProperty(operation.from));
ErrorReporter(error);
return;
}
}
}
public void Test(Operation operation, object objectToApplyTo)
{
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
var parsedPath = new ParsedPath(operation.path);
var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory);
var target = objectToApplyTo;
if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage))
{
var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage);
ErrorReporter(error);
return;
}
if (!adapter.TryTest(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage))
{
var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage);
ErrorReporter(error);
return;
}
}
private bool TryGetValue(
string fromLocation,
object objectToGetValueFrom,
Operation operation,
out object propertyValue)
{
if (fromLocation == null)
{
throw new ArgumentNullException(nameof(fromLocation));
}
if (objectToGetValueFrom == null)
{
throw new ArgumentNullException(nameof(objectToGetValueFrom));
}
if (operation == null)
{
throw new ArgumentNullException(nameof(operation));
}
propertyValue = null;
var parsedPath = new ParsedPath(fromLocation);
var visitor = new ObjectVisitor(parsedPath, ContractResolver, AdapterFactory);
var target = objectToGetValueFrom;
if (!visitor.TryVisit(ref target, out var adapter, out var errorMessage))
{
var error = CreatePathNotFoundError(objectToGetValueFrom, fromLocation, operation, errorMessage);
ErrorReporter(error);
return false;
}
if (!adapter.TryGet(target, parsedPath.LastSegment, ContractResolver, out propertyValue, out errorMessage))
{
var error = CreateOperationFailedError(objectToGetValueFrom, fromLocation, operation, errorMessage);
ErrorReporter(error);
return false;
}
return true;
}
private Action<JsonPatchError> ErrorReporter
{
get
{
return LogErrorAction ?? Internal.ErrorReporter.Default;
}
}
private JsonPatchError CreateOperationFailedError(object target, string path, Operation operation, string errorMessage)
{
return new JsonPatchError(
target,
operation,
errorMessage ?? Resources.FormatCannotPerformOperation(operation.op, path));
}
private JsonPatchError CreatePathNotFoundError(object target, string path, Operation operation, string errorMessage)
{
return new JsonPatchError(
target,
operation,
errorMessage ?? Resources.FormatTargetLocationNotFound(operation.op, path));
}
}
}

View File

@ -0,0 +1,76 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Converters
{
public class JsonPatchDocumentConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
if (objectType != typeof(JsonPatchDocument))
{
throw new ArgumentException(Resources.FormatParameterMustMatchType("objectType", "JsonPatchDocument"), "objectType");
}
try
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
// load jObject
var jObject = JArray.Load(reader);
// Create target object for Json => list of operations
var targetOperations = new List<Operation>();
// Create a new reader for this jObject, and set all properties
// to match the original reader.
var jObjectReader = jObject.CreateReader();
jObjectReader.Culture = reader.Culture;
jObjectReader.DateParseHandling = reader.DateParseHandling;
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
// Populate the object properties
serializer.Populate(jObjectReader, targetOperations);
// container target: the JsonPatchDocument.
var container = new JsonPatchDocument(targetOperations, new DefaultContractResolver());
return container;
}
catch (Exception ex)
{
throw new JsonSerializationException(Resources.InvalidJsonPatchDocument, ex);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is IJsonPatchDocument)
{
var jsonPatchDoc = (IJsonPatchDocument)value;
var lst = jsonPatchDoc.GetOperations();
// write out the operations, no envelope
serializer.Serialize(writer, lst);
}
}
}
}

View File

@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Converters
{
public class TypedJsonPatchDocumentConverter : JsonPatchDocumentConverter
{
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
try
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
var genericType = objectType.GetTypeInfo().GenericTypeArguments[0];
// load jObject
var jObject = JArray.Load(reader);
// Create target object for Json => list of operations, typed to genericType
var genericOperation = typeof(Operation<>);
var concreteOperationType = genericOperation.MakeGenericType(genericType);
var genericList = typeof(List<>);
var concreteList = genericList.MakeGenericType(concreteOperationType);
var targetOperations = Activator.CreateInstance(concreteList);
//Create a new reader for this jObject, and set all properties to match the original reader.
var jObjectReader = jObject.CreateReader();
jObjectReader.Culture = reader.Culture;
jObjectReader.DateParseHandling = reader.DateParseHandling;
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
// Populate the object properties
serializer.Populate(jObjectReader, targetOperations);
// container target: the typed JsonPatchDocument.
var container = Activator.CreateInstance(objectType, targetOperations, new DefaultContractResolver());
return container;
}
catch (Exception ex)
{
throw new JsonSerializationException(Resources.InvalidJsonPatchDocument, ex);
}
}
}
}

View File

@ -0,0 +1,38 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Operations;
namespace Microsoft.AspNetCore.JsonPatch.Exceptions
{
public class JsonPatchException : Exception
{
public Operation FailedOperation { get; private set; }
public object AffectedObject { get; private set; }
public JsonPatchException()
{
}
public JsonPatchException(JsonPatchError jsonPatchError, Exception innerException)
: base(jsonPatchError.ErrorMessage, innerException)
{
FailedOperation = jsonPatchError.Operation;
AffectedObject = jsonPatchError.AffectedObject;
}
public JsonPatchException(JsonPatchError jsonPatchError)
: this(jsonPatchError, null)
{
}
public JsonPatchException(string message, Exception innerException)
: base (message, innerException)
{
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.JsonPatch.Helpers
{
/// <summary>
/// Return value for the helper method used by Copy/Move. Needed to ensure we can make a different
/// decision in the calling method when the value is null because it cannot be fetched (HasError = true)
/// versus when it actually is null (much like why RemovedPropertyTypeResult is used for returning
/// type in the Remove operation).
/// </summary>
public class GetValueResult
{
public GetValueResult(object propertyValue, bool hasError)
{
PropertyValue = propertyValue;
HasError = hasError;
}
/// <summary>
/// The value of the property we're trying to get
/// </summary>
public object PropertyValue { get; private set; }
/// <summary>
/// HasError: true when an error occurred, the operation didn't complete succesfully
/// </summary>
public bool HasError { get; private set; }
}
}

View File

@ -0,0 +1,43 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch
{
/// <summary>
/// Metadata for JsonProperty.
/// </summary>
public class JsonPatchProperty
{
/// <summary>
/// Initializes a new instance.
/// </summary>
public JsonPatchProperty(JsonProperty property, object parent)
{
if (property == null)
{
throw new ArgumentNullException(nameof(property));
}
if (parent == null)
{
throw new ArgumentNullException(nameof(parent));
}
Property = property;
Parent = parent;
}
/// <summary>
/// Gets or sets JsonProperty.
/// </summary>
public JsonProperty Property { get; set; }
/// <summary>
/// Gets or sets Parent.
/// </summary>
public object Parent { get; set; }
}
}

View File

@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.JsonPatch.Operations;
using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch
{
public interface IJsonPatchDocument
{
IContractResolver ContractResolver { get; set; }
IList<Operation> GetOperations();
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class ConversionResult
{
public ConversionResult(bool canBeConverted, object convertedInstance)
{
CanBeConverted = canBeConverted;
ConvertedInstance = convertedInstance;
}
public bool CanBeConverted { get; }
public object ConvertedInstance { get; }
}
}

View File

@ -0,0 +1,75 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public static class ConversionResultProvider
{
public static ConversionResult ConvertTo(object value, Type typeToConvertTo)
{
if (value == null)
{
return new ConversionResult(IsNullableType(typeToConvertTo), null);
}
else if (typeToConvertTo.IsAssignableFrom(value.GetType()))
{
// No need to convert
return new ConversionResult(true, value);
}
else
{
try
{
var deserialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), typeToConvertTo);
return new ConversionResult(true, deserialized);
}
catch
{
return new ConversionResult(canBeConverted: false, convertedInstance: null);
}
}
}
public static ConversionResult CopyTo(object value, Type typeToConvertTo)
{
var targetType = typeToConvertTo;
if (value == null)
{
return new ConversionResult(canBeConverted: true, convertedInstance: null);
}
else if (typeToConvertTo.IsAssignableFrom(value.GetType()))
{
// Keep original type
targetType = value.GetType();
}
try
{
var deserialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(value), targetType);
return new ConversionResult(true, deserialized);
}
catch
{
return new ConversionResult(canBeConverted: false, convertedInstance: null);
}
}
private static bool IsNullableType(Type type)
{
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsValueType)
{
// value types are only nullable if they are Nullable<T>
return typeInfo.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
else
{
// reference types are always nullable
return true;
}
}
}
}

View File

@ -0,0 +1,245 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class DictionaryAdapter<TKey, TValue> : IAdapter
{
public virtual bool TryAdd(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType());
var key = contract.DictionaryKeyResolver(segment);
var dictionary = (IDictionary<TKey, TValue>)target;
// As per JsonPatch spec, if a key already exists, adding should replace the existing value
if (!TryConvertKey(key, out var convertedKey, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, out var convertedValue, out errorMessage))
{
return false;
}
dictionary[convertedKey] = convertedValue;
errorMessage = null;
return true;
}
public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType());
var key = contract.DictionaryKeyResolver(segment);
var dictionary = (IDictionary<TKey, TValue>)target;
if (!TryConvertKey(key, out var convertedKey, out errorMessage))
{
value = null;
return false;
}
if (!dictionary.ContainsKey(convertedKey))
{
value = null;
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
value = dictionary[convertedKey];
errorMessage = null;
return true;
}
public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
out string errorMessage)
{
var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType());
var key = contract.DictionaryKeyResolver(segment);
var dictionary = (IDictionary<TKey, TValue>)target;
if (!TryConvertKey(key, out var convertedKey, out errorMessage))
{
return false;
}
// As per JsonPatch spec, the target location must exist for remove to be successful
if (!dictionary.ContainsKey(convertedKey))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
dictionary.Remove(convertedKey);
errorMessage = null;
return true;
}
public virtual bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType());
var key = contract.DictionaryKeyResolver(segment);
var dictionary = (IDictionary<TKey, TValue>)target;
if (!TryConvertKey(key, out var convertedKey, out errorMessage))
{
return false;
}
// As per JsonPatch spec, the target location must exist for remove to be successful
if (!dictionary.ContainsKey(convertedKey))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
if (!TryConvertValue(value, out var convertedValue, out errorMessage))
{
return false;
}
dictionary[convertedKey] = convertedValue;
errorMessage = null;
return true;
}
public virtual bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType());
var key = contract.DictionaryKeyResolver(segment);
var dictionary = (IDictionary<TKey, TValue>)target;
if (!TryConvertKey(key, out var convertedKey, out errorMessage))
{
return false;
}
// As per JsonPatch spec, the target location must exist for test to be successful
if (!dictionary.ContainsKey(convertedKey))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
if (!TryConvertValue(value, out var convertedValue, out errorMessage))
{
return false;
}
var currentValue = dictionary[convertedKey];
// The target segment does not have an assigned value to compare the test value with
if (currentValue == null || string.IsNullOrEmpty(currentValue.ToString()))
{
errorMessage = Resources.FormatValueForTargetSegmentCannotBeNullOrEmpty(segment);
return false;
}
if (!JToken.DeepEquals(JsonConvert.SerializeObject(currentValue), JsonConvert.SerializeObject(convertedValue)))
{
errorMessage = Resources.FormatValueNotEqualToTestValue(currentValue, value, segment);
return false;
}
else
{
errorMessage = null;
return true;
}
}
public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
out object nextTarget,
out string errorMessage)
{
var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType());
var key = contract.DictionaryKeyResolver(segment);
var dictionary = (IDictionary<TKey, TValue>)target;
if (!TryConvertKey(key, out var convertedKey, out errorMessage))
{
nextTarget = null;
return false;
}
if (dictionary.ContainsKey(convertedKey))
{
nextTarget = dictionary[convertedKey];
errorMessage = null;
return true;
}
else
{
nextTarget = null;
errorMessage = null;
return false;
}
}
protected virtual bool TryConvertKey(string key, out TKey convertedKey, out string errorMessage)
{
var conversionResult = ConversionResultProvider.ConvertTo(key, typeof(TKey));
if (conversionResult.CanBeConverted)
{
errorMessage = null;
convertedKey = (TKey)conversionResult.ConvertedInstance;
return true;
}
else
{
errorMessage = Resources.FormatInvalidPathSegment(key);
convertedKey = default(TKey);
return false;
}
}
protected virtual bool TryConvertValue(object value, out TValue convertedValue, out string errorMessage)
{
var conversionResult = ConversionResultProvider.ConvertTo(value, typeof(TValue));
if (conversionResult.CanBeConverted)
{
errorMessage = null;
convertedValue = (TValue)conversionResult.ConvertedInstance;
return true;
}
else
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
convertedValue = default(TValue);
return false;
}
}
}
}

View File

@ -0,0 +1,248 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.CSharp.RuntimeBinder;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using CSharpBinder = Microsoft.CSharp.RuntimeBinder;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class DynamicObjectAdapter : IAdapter
{
public virtual bool TryAdd(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
if (!TrySetDynamicObjectProperty(target, contractResolver, segment, value, out errorMessage))
{
return false;
}
errorMessage = null;
return true;
}
public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out value, out errorMessage))
{
value = null;
return false;
}
errorMessage = null;
return true;
}
public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
return false;
}
// Setting the value to "null" will use the default value in case of value types, and
// null in case of reference types
object value = null;
if (property.GetType().GetTypeInfo().IsValueType
&& Nullable.GetUnderlyingType(property.GetType()) == null)
{
value = Activator.CreateInstance(property.GetType());
}
if (!TrySetDynamicObjectProperty(target, contractResolver, segment, value, out errorMessage))
{
return false;
}
errorMessage = null;
return true;
}
public virtual bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, property.GetType(), out var convertedValue))
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
return false;
}
if (!TryRemove(target, segment, contractResolver, out errorMessage))
{
return false;
}
if (!TrySetDynamicObjectProperty(target, contractResolver, segment, convertedValue, out errorMessage))
{
return false;
}
errorMessage = null;
return true;
}
public virtual bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, property.GetType(), out var convertedValue))
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
return false;
}
if (!JToken.DeepEquals(JsonConvert.SerializeObject(property), JsonConvert.SerializeObject(convertedValue)))
{
errorMessage = Resources.FormatValueNotEqualToTestValue(property, value, segment);
return false;
}
else
{
errorMessage = null;
return true;
}
}
public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
out object nextTarget,
out string errorMessage)
{
if (!TryGetDynamicObjectProperty(target, contractResolver, segment, out var property, out errorMessage))
{
nextTarget = null;
return false;
}
else
{
nextTarget = property;
errorMessage = null;
return true;
}
}
protected virtual bool TryGetDynamicObjectProperty(
object target,
IContractResolver contractResolver,
string segment,
out object value,
out string errorMessage)
{
var jsonDynamicContract = (JsonDynamicContract)contractResolver.ResolveContract(target.GetType());
var propertyName = jsonDynamicContract.PropertyNameResolver(segment);
var binder = CSharpBinder.Binder.GetMember(
CSharpBinderFlags.None,
propertyName,
target.GetType(),
new List<CSharpArgumentInfo>
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
});
var callsite = CallSite<Func<CallSite, object, object>>.Create(binder);
try
{
value = callsite.Target(callsite, target);
errorMessage = null;
return true;
}
catch (RuntimeBinderException)
{
value = null;
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
}
protected virtual bool TrySetDynamicObjectProperty(
object target,
IContractResolver contractResolver,
string segment,
object value,
out string errorMessage)
{
var jsonDynamicContract = (JsonDynamicContract)contractResolver.ResolveContract(target.GetType());
var propertyName = jsonDynamicContract.PropertyNameResolver(segment);
var binder = CSharpBinder.Binder.SetMember(
CSharpBinderFlags.None,
propertyName,
target.GetType(),
new List<CSharpArgumentInfo>
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
});
var callsite = CallSite<Func<CallSite, object, object, object>>.Create(binder);
try
{
callsite.Target(callsite, target, value);
errorMessage = null;
return true;
}
catch (RuntimeBinderException)
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
}
protected virtual bool TryConvertValue(object value, Type propertyType, out object convertedValue)
{
var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType);
if (!conversionResult.CanBeConverted)
{
convertedValue = null;
return false;
}
convertedValue = conversionResult.ConvertedInstance;
return true;
}
}
}

View File

@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Exceptions;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
internal static class ErrorReporter
{
public static readonly Action<JsonPatchError> Default = (error) =>
{
throw new JsonPatchException(error);
};
}
}

View File

@ -0,0 +1,51 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public interface IAdapter
{
bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
out object nextTarget,
out string errorMessage);
bool TryAdd(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage);
bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
out string errorMessage);
bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage);
bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage);
bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage);
}
}

View File

@ -0,0 +1,349 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Extensions.Internal;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class ListAdapter : IAdapter
{
public virtual bool TryAdd(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
var list = (IList)target;
if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage))
{
return false;
}
if (!TryGetPositionInfo(list, segment, OperationType.Add, out var positionInfo, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, typeArgument, segment, out var convertedValue, out errorMessage))
{
return false;
}
if (positionInfo.Type == PositionType.EndOfList)
{
list.Add(convertedValue);
}
else
{
list.Insert(positionInfo.Index, convertedValue);
}
errorMessage = null;
return true;
}
public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
var list = (IList)target;
if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage))
{
value = null;
return false;
}
if (!TryGetPositionInfo(list, segment, OperationType.Get, out var positionInfo, out errorMessage))
{
value = null;
return false;
}
if (positionInfo.Type == PositionType.EndOfList)
{
value = list[list.Count - 1];
}
else
{
value = list[positionInfo.Index];
}
errorMessage = null;
return true;
}
public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
out string errorMessage)
{
var list = (IList)target;
if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage))
{
return false;
}
if (!TryGetPositionInfo(list, segment, OperationType.Remove, out var positionInfo, out errorMessage))
{
return false;
}
if (positionInfo.Type == PositionType.EndOfList)
{
list.RemoveAt(list.Count - 1);
}
else
{
list.RemoveAt(positionInfo.Index);
}
errorMessage = null;
return true;
}
public virtual bool TryReplace(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
var list = (IList)target;
if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage))
{
return false;
}
if (!TryGetPositionInfo(list, segment, OperationType.Replace, out var positionInfo, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, typeArgument, segment, out var convertedValue, out errorMessage))
{
return false;
}
if (positionInfo.Type == PositionType.EndOfList)
{
list[list.Count - 1] = convertedValue;
}
else
{
list[positionInfo.Index] = convertedValue;
}
errorMessage = null;
return true;
}
public virtual bool TryTest(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
var list = (IList)target;
if (!TryGetListTypeArgument(list, out var typeArgument, out errorMessage))
{
return false;
}
if (!TryGetPositionInfo(list, segment, OperationType.Replace, out var positionInfo, out errorMessage))
{
return false;
}
if (!TryConvertValue(value, typeArgument, segment, out var convertedValue, out errorMessage))
{
return false;
}
var currentValue = list[positionInfo.Index];
if (!JToken.DeepEquals(JsonConvert.SerializeObject(currentValue), JsonConvert.SerializeObject(convertedValue)))
{
errorMessage = Resources.FormatValueAtListPositionNotEqualToTestValue(currentValue, value, positionInfo.Index);
return false;
}
else
{
errorMessage = null;
return true;
}
}
public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
var list = target as IList;
if (list == null)
{
value = null;
errorMessage = null;
return false;
}
var index = -1;
if (!int.TryParse(segment, out index))
{
value = null;
errorMessage = Resources.FormatInvalidIndexValue(segment);
return false;
}
if (index < 0 || index >= list.Count)
{
value = null;
errorMessage = Resources.FormatIndexOutOfBounds(segment);
return false;
}
value = list[index];
errorMessage = null;
return true;
}
protected virtual bool TryConvertValue(
object originalValue,
Type listTypeArgument,
string segment,
out object convertedValue,
out string errorMessage)
{
var conversionResult = ConversionResultProvider.ConvertTo(originalValue, listTypeArgument);
if (!conversionResult.CanBeConverted)
{
convertedValue = null;
errorMessage = Resources.FormatInvalidValueForProperty(originalValue);
return false;
}
convertedValue = conversionResult.ConvertedInstance;
errorMessage = null;
return true;
}
protected virtual bool TryGetListTypeArgument(IList list, out Type listTypeArgument, out string errorMessage)
{
// Arrays are not supported as they have fixed size and operations like Add, Insert do not make sense
var listType = list.GetType();
if (listType.IsArray)
{
errorMessage = Resources.FormatPatchNotSupportedForArrays(listType.FullName);
listTypeArgument = null;
return false;
}
else
{
var genericList = ClosedGenericMatcher.ExtractGenericInterface(listType, typeof(IList<>));
if (genericList == null)
{
errorMessage = Resources.FormatPatchNotSupportedForNonGenericLists(listType.FullName);
listTypeArgument = null;
return false;
}
else
{
listTypeArgument = genericList.GenericTypeArguments[0];
errorMessage = null;
return true;
}
}
}
protected virtual bool TryGetPositionInfo(
IList list,
string segment,
OperationType operationType,
out PositionInfo positionInfo,
out string errorMessage)
{
if (segment == "-")
{
positionInfo = new PositionInfo(PositionType.EndOfList, -1);
errorMessage = null;
return true;
}
var position = -1;
if (int.TryParse(segment, out position))
{
if (position >= 0 && position < list.Count)
{
positionInfo = new PositionInfo(PositionType.Index, position);
errorMessage = null;
return true;
}
// As per JSON Patch spec, for Add operation the index value representing the number of elements is valid,
// where as for other operations like Remove, Replace, Move and Copy the target index MUST exist.
else if (position == list.Count && operationType == OperationType.Add)
{
positionInfo = new PositionInfo(PositionType.EndOfList, -1);
errorMessage = null;
return true;
}
else
{
positionInfo = new PositionInfo(PositionType.OutOfBounds, position);
errorMessage = Resources.FormatIndexOutOfBounds(segment);
return false;
}
}
else
{
positionInfo = new PositionInfo(PositionType.Invalid, -1);
errorMessage = Resources.FormatInvalidIndexValue(segment);
return false;
}
}
protected struct PositionInfo
{
public PositionInfo(PositionType type, int index)
{
Type = type;
Index = index;
}
public PositionType Type { get; }
public int Index { get; }
}
protected enum PositionType
{
Index, // valid index
EndOfList, // '-'
Invalid, // Ex: not an integer
OutOfBounds
}
protected enum OperationType
{
Add,
Remove,
Get,
Replace
}
}
}

View File

@ -0,0 +1,79 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Adapters;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class ObjectVisitor
{
private readonly IAdapterFactory _adapterFactory;
private readonly IContractResolver _contractResolver;
private readonly ParsedPath _path;
/// <summary>
/// Initializes a new instance of <see cref="ObjectVisitor"/>.
/// </summary>
/// <param name="path">The path of the JsonPatch operation</param>
/// <param name="contractResolver">The <see cref="IContractResolver"/>.</param>
public ObjectVisitor(ParsedPath path, IContractResolver contractResolver)
:this(path, contractResolver, new AdapterFactory())
{
}
/// <summary>
/// Initializes a new instance of <see cref="ObjectVisitor"/>.
/// </summary>
/// <param name="path">The path of the JsonPatch operation</param>
/// <param name="contractResolver">The <see cref="IContractResolver"/>.</param>
/// <param name="adapterFactory">The <see cref="IAdapterFactory"/> to use when creating adaptors.</param>
public ObjectVisitor(ParsedPath path, IContractResolver contractResolver, IAdapterFactory adapterFactory)
{
_path = path;
_contractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
_adapterFactory = adapterFactory ?? throw new ArgumentNullException(nameof(adapterFactory));
}
public bool TryVisit(ref object target, out IAdapter adapter, out string errorMessage)
{
if (target == null)
{
adapter = null;
errorMessage = null;
return false;
}
adapter = SelectAdapter(target);
// Traverse until the penultimate segment to get the target object and adapter
for (var i = 0; i < _path.Segments.Count - 1; i++)
{
if (!adapter.TryTraverse(target, _path.Segments[i], _contractResolver, out var next, out errorMessage))
{
adapter = null;
return false;
}
// If we hit a null on an interior segment then we need to stop traversing.
if (next == null)
{
adapter = null;
return false;
}
target = next;
adapter = SelectAdapter(target);
}
errorMessage = null;
return true;
}
private IAdapter SelectAdapter(object targetObject)
{
return _adapterFactory.Create(targetObject, _contractResolver);
}
}
}

View File

@ -0,0 +1,92 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.JsonPatch.Exceptions;
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public struct ParsedPath
{
private static readonly string[] Empty = null;
private readonly string[] _segments;
public ParsedPath(string path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
_segments = ParsePath(path);
}
public string LastSegment
{
get
{
if (_segments == null || _segments.Length == 0)
{
return null;
}
return _segments[_segments.Length - 1];
}
}
public IReadOnlyList<string> Segments => _segments ?? Empty;
private static string[] ParsePath(string path)
{
var strings = new List<string>();
var sb = new StringBuilder(path.Length);
for (var i = 0; i < path.Length; i++)
{
if (path[i] == '/')
{
if (sb.Length > 0)
{
strings.Add(sb.ToString());
sb.Length = 0;
}
}
else if (path[i] == '~')
{
++i;
if (i >= path.Length)
{
throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null);
}
if (path[i] == '0')
{
sb.Append('~');
}
else if (path[i] == '1')
{
sb.Append('/');
}
else
{
throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null);
}
}
else
{
sb.Append(path[i]);
}
}
if (sb.Length > 0)
{
strings.Add(sb.ToString());
}
return strings.ToArray();
}
}
}

View File

@ -0,0 +1,32 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.JsonPatch.Exceptions;
using System;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
internal static class PathHelpers
{
internal static string ValidateAndNormalizePath(string path)
{
// check for most common path errors on create. This is not
// absolutely necessary, but it allows us to already catch mistakes
// on creation of the patch document rather than on execute.
if (path.Contains("//"))
{
throw new JsonPatchException(Resources.FormatInvalidValueForPath(path), null);
}
if (!path.StartsWith("/", StringComparison.Ordinal))
{
return "/" + path;
}
else
{
return path;
}
}
}
}

View File

@ -0,0 +1,236 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch.Internal
{
public class PocoAdapter : IAdapter
{
public virtual bool TryAdd(
object target,
string segment,
IContractResolver contractResolver,
object value,
out string errorMessage)
{
if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
if (!jsonProperty.Writable)
{
errorMessage = Resources.FormatCannotUpdateProperty(segment);
return false;
}
if (!TryConvertValue(value, jsonProperty.PropertyType, out var convertedValue))
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
return false;
}
jsonProperty.ValueProvider.SetValue(target, convertedValue);
errorMessage = null;
return true;
}
public virtual bool TryGet(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
value = null;
return false;
}
if (!jsonProperty.Readable)
{
errorMessage = Resources.FormatCannotReadProperty(segment);
value = null;
return false;
}
value = jsonProperty.ValueProvider.GetValue(target);
errorMessage = null;
return true;
}
public virtual bool TryRemove(
object target,
string segment,
IContractResolver contractResolver,
out string errorMessage)
{
if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
if (!jsonProperty.Writable)
{
errorMessage = Resources.FormatCannotUpdateProperty(segment);
return false;
}
// Setting the value to "null" will use the default value in case of value types, and
// null in case of reference types
object value = null;
if (jsonProperty.PropertyType.GetTypeInfo().IsValueType
&& Nullable.GetUnderlyingType(jsonProperty.PropertyType) == null)
{
value = Activator.CreateInstance(jsonProperty.PropertyType);
}
jsonProperty.ValueProvider.SetValue(target, value);
errorMessage = null;
return true;
}
public virtual bool TryReplace(
object target,
string segment,
IContractResolver
contractResolver,
object value,
out string errorMessage)
{
if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
if (!jsonProperty.Writable)
{
errorMessage = Resources.FormatCannotUpdateProperty(segment);
return false;
}
if (!TryConvertValue(value, jsonProperty.PropertyType, out var convertedValue))
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
return false;
}
jsonProperty.ValueProvider.SetValue(target, convertedValue);
errorMessage = null;
return true;
}
public virtual bool TryTest(
object target,
string segment,
IContractResolver
contractResolver,
object value,
out string errorMessage)
{
if (!TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty))
{
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
if (!jsonProperty.Readable)
{
errorMessage = Resources.FormatCannotReadProperty(segment);
return false;
}
if (!TryConvertValue(value, jsonProperty.PropertyType, out var convertedValue))
{
errorMessage = Resources.FormatInvalidValueForProperty(value);
return false;
}
var currentValue = jsonProperty.ValueProvider.GetValue(target);
if (!JToken.DeepEquals(JsonConvert.SerializeObject(currentValue), JsonConvert.SerializeObject(convertedValue)))
{
errorMessage = Resources.FormatValueNotEqualToTestValue(currentValue, value, segment);
return false;
}
errorMessage = null;
return true;
}
public virtual bool TryTraverse(
object target,
string segment,
IContractResolver contractResolver,
out object value,
out string errorMessage)
{
if (target == null)
{
value = null;
errorMessage = null;
return false;
}
if (TryGetJsonProperty(target, contractResolver, segment, out var jsonProperty))
{
value = jsonProperty.ValueProvider.GetValue(target);
errorMessage = null;
return true;
}
value = null;
errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment);
return false;
}
protected virtual bool TryGetJsonProperty(
object target,
IContractResolver contractResolver,
string segment,
out JsonProperty jsonProperty)
{
if (contractResolver.ResolveContract(target.GetType()) is JsonObjectContract jsonObjectContract)
{
var pocoProperty = jsonObjectContract
.Properties
.FirstOrDefault(p => string.Equals(p.PropertyName, segment, StringComparison.OrdinalIgnoreCase));
if (pocoProperty != null)
{
jsonProperty = pocoProperty;
return true;
}
}
jsonProperty = null;
return false;
}
protected virtual bool TryConvertValue(object value, Type propertyType, out object convertedValue)
{
var conversionResult = ConversionResultProvider.ConvertTo(value, propertyType);
if (!conversionResult.CanBeConverted)
{
convertedValue = null;
return false;
}
convertedValue = conversionResult.ConvertedInstance;
return true;
}
}
}

View File

@ -0,0 +1,271 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.JsonPatch.Adapters;
using Microsoft.AspNetCore.JsonPatch.Converters;
using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Microsoft.AspNetCore.JsonPatch.Internal;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch
{
// Implementation details: the purpose of this type of patch document is to allow creation of such
// documents for cases where there's no class/DTO to work on. Typical use case: backend not built in
// .NET or architecture doesn't contain a shared DTO layer.
[JsonConverter(typeof(JsonPatchDocumentConverter))]
public class JsonPatchDocument : IJsonPatchDocument
{
public List<Operation> Operations { get; private set; }
[JsonIgnore]
public IContractResolver ContractResolver { get; set; }
public JsonPatchDocument()
{
Operations = new List<Operation>();
ContractResolver = new DefaultContractResolver();
}
public JsonPatchDocument(List<Operation> operations, IContractResolver contractResolver)
{
if (operations == null)
{
throw new ArgumentNullException(nameof(operations));
}
if (contractResolver == null)
{
throw new ArgumentNullException(nameof(contractResolver));
}
Operations = operations;
ContractResolver = contractResolver;
}
/// <summary>
/// Add operation. Will result in, for example,
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
/// </summary>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument Add(string path, object value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation("add", PathHelpers.ValidateAndNormalizePath(path), null, value));
return this;
}
/// <summary>
/// Remove value at target location. Will result in, for example,
/// { "op": "remove", "path": "/a/b/c" }
/// </summary>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument Remove(string path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation("remove", PathHelpers.ValidateAndNormalizePath(path), null, null));
return this;
}
/// <summary>
/// Replace value. Will result in, for example,
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
/// </summary>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument Replace(string path, object value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation("replace", PathHelpers.ValidateAndNormalizePath(path), null, value));
return this;
}
/// <summary>
/// Test value. Will result in, for example,
/// { "op": "test", "path": "/a/b/c", "value": 42 }
/// </summary>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument Test(string path, object value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation("test", PathHelpers.ValidateAndNormalizePath(path), null, value));
return this;
}
/// <summary>
/// Removes value at specified location and add it to the target location. Will result in, for example:
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
/// </summary>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument Move(string from, string path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation("move", PathHelpers.ValidateAndNormalizePath(path), PathHelpers.ValidateAndNormalizePath(from)));
return this;
}
/// <summary>
/// Copy the value at specified location to the target location. Will result in, for example:
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
/// </summary>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument Copy(string from, string path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation("copy", PathHelpers.ValidateAndNormalizePath(path), PathHelpers.ValidateAndNormalizePath(from)));
return this;
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
public void ApplyTo(object objectToApplyTo)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, new AdapterFactory()));
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
/// <param name="logErrorAction">Action to log errors</param>
public void ApplyTo(object objectToApplyTo, Action<JsonPatchError> logErrorAction)
{
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction, new AdapterFactory()), logErrorAction);
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
/// <param name="adapter">IObjectAdapter instance to use when applying</param>
/// <param name="logErrorAction">Action to log errors</param>
public void ApplyTo(object objectToApplyTo, IObjectAdapter adapter, Action<JsonPatchError> logErrorAction)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}
foreach (var op in Operations)
{
try
{
op.Apply(objectToApplyTo, adapter);
}
catch (JsonPatchException jsonPatchException)
{
var errorReporter = logErrorAction ?? ErrorReporter.Default;
errorReporter(new JsonPatchError(objectToApplyTo, op, jsonPatchException.Message));
// As per JSON Patch spec if an operation results in error, further operations should not be executed.
break;
}
}
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
/// <param name="adapter">IObjectAdapter instance to use when applying</param>
public void ApplyTo(object objectToApplyTo, IObjectAdapter adapter)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}
// apply each operation in order
foreach (var op in Operations)
{
op.Apply(objectToApplyTo, adapter);
}
}
IList<Operation> IJsonPatchDocument.GetOperations()
{
var allOps = new List<Operation>();
if (Operations != null)
{
foreach (var op in Operations)
{
var untypedOp = new Operation();
untypedOp.op = op.op;
untypedOp.value = op.value;
untypedOp.path = op.path;
untypedOp.from = op.from;
allOps.Add(untypedOp);
}
}
return allOps;
}
}
}

View File

@ -0,0 +1,884 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Linq.Expressions;
using Microsoft.AspNetCore.JsonPatch.Adapters;
using Microsoft.AspNetCore.JsonPatch.Converters;
using Microsoft.AspNetCore.JsonPatch.Exceptions;
using Microsoft.AspNetCore.JsonPatch.Internal;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Microsoft.AspNetCore.JsonPatch
{
// Implementation details: the purpose of this type of patch document is to ensure we can do type-checking
// when producing a JsonPatchDocument. However, we cannot send this "typed" over the wire, as that would require
// including type data in the JsonPatchDocument serialized as JSON (to allow for correct deserialization) - that's
// not according to RFC 6902, and would thus break cross-platform compatibility.
[JsonConverter(typeof(TypedJsonPatchDocumentConverter))]
public class JsonPatchDocument<TModel> : IJsonPatchDocument where TModel : class
{
public List<Operation<TModel>> Operations { get; private set; }
[JsonIgnore]
public IContractResolver ContractResolver { get; set; }
public JsonPatchDocument()
{
Operations = new List<Operation<TModel>>();
ContractResolver = new DefaultContractResolver();
}
// Create from list of operations
public JsonPatchDocument(List<Operation<TModel>> operations, IContractResolver contractResolver)
{
Operations = operations ?? throw new ArgumentNullException(nameof(operations));
ContractResolver = contractResolver ?? throw new ArgumentNullException(nameof(contractResolver));
}
/// <summary>
/// Add operation. Will result in, for example,
/// { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Add<TProp>(Expression<Func<TModel, TProp>> path, TProp value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"add",
GetPath(path, null),
from: null,
value: value));
return this;
}
/// <summary>
/// Add value to list at given position
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <param name="position">position</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Add<TProp>(
Expression<Func<TModel, IList<TProp>>> path,
TProp value,
int position)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"add",
GetPath(path, position.ToString()),
from: null,
value: value));
return this;
}
/// <summary>
/// Add value to the end of the list
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Add<TProp>(Expression<Func<TModel, IList<TProp>>> path, TProp value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"add",
GetPath(path, "-"),
from: null,
value: value));
return this;
}
/// <summary>
/// Remove value at target location. Will result in, for example,
/// { "op": "remove", "path": "/a/b/c" }
/// </summary>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Remove<TProp>(Expression<Func<TModel, TProp>> path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>("remove", GetPath(path, null), from: null));
return this;
}
/// <summary>
/// Remove value from list at given position
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="position">position</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Remove<TProp>(Expression<Func<TModel, IList<TProp>>> path, int position)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"remove",
GetPath(path, position.ToString()),
from: null));
return this;
}
/// <summary>
/// Remove value from end of list
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Remove<TProp>(Expression<Func<TModel, IList<TProp>>> path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"remove",
GetPath(path, "-"),
from: null));
return this;
}
/// <summary>
/// Replace value. Will result in, for example,
/// { "op": "replace", "path": "/a/b/c", "value": 42 }
/// </summary>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Replace<TProp>(Expression<Func<TModel, TProp>> path, TProp value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"replace",
GetPath(path, null),
from: null,
value: value));
return this;
}
/// <summary>
/// Replace value in a list at given position
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <param name="position">position</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Replace<TProp>(Expression<Func<TModel, IList<TProp>>> path,
TProp value, int position)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"replace",
GetPath(path, position.ToString()),
from: null,
value: value));
return this;
}
/// <summary>
/// Replace value at end of a list
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Replace<TProp>(Expression<Func<TModel, IList<TProp>>> path, TProp value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"replace",
GetPath(path, "-"),
from: null,
value: value));
return this;
}
/// <summary>
/// Test value. Will result in, for example,
/// { "op": "test", "path": "/a/b/c", "value": 42 }
/// </summary>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Test<TProp>(Expression<Func<TModel, TProp>> path, TProp value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"test",
GetPath(path, null),
from: null,
value: value));
return this;
}
/// <summary>
/// Test value in a list at given position
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <param name="position">position</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Test<TProp>(Expression<Func<TModel, IList<TProp>>> path,
TProp value, int position)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"test",
GetPath(path, position.ToString()),
from: null,
value: value));
return this;
}
/// <summary>
/// Test value at end of a list
/// </summary>
/// <typeparam name="TProp">value type</typeparam>
/// <param name="path">target location</param>
/// <param name="value">value</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Test<TProp>(Expression<Func<TModel, IList<TProp>>> path, TProp value)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"test",
GetPath(path, "-"),
from: null,
value: value));
return this;
}
/// <summary>
/// Removes value at specified location and add it to the target location. Will result in, for example:
/// { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }
/// </summary>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Move<TProp>(
Expression<Func<TModel, TProp>> from,
Expression<Func<TModel, TProp>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"move",
GetPath(path, null),
GetPath(from, null)));
return this;
}
/// <summary>
/// Move from a position in a list to a new location
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="positionFrom">position</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Move<TProp>(
Expression<Func<TModel, IList<TProp>>> from,
int positionFrom,
Expression<Func<TModel, TProp>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"move",
GetPath(path, null),
GetPath(from, positionFrom.ToString())));
return this;
}
/// <summary>
/// Move from a property to a location in a list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <param name="positionTo">position</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Move<TProp>(
Expression<Func<TModel, TProp>> from,
Expression<Func<TModel, IList<TProp>>> path,
int positionTo)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"move",
GetPath(path, positionTo.ToString()),
GetPath(from, null)));
return this;
}
/// <summary>
/// Move from a position in a list to another location in a list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="positionFrom">position (source)</param>
/// <param name="path">target location</param>
/// <param name="positionTo">position (target)</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Move<TProp>(
Expression<Func<TModel, IList<TProp>>> from,
int positionFrom,
Expression<Func<TModel, IList<TProp>>> path,
int positionTo)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"move",
GetPath(path, positionTo.ToString()),
GetPath(from, positionFrom.ToString())));
return this;
}
/// <summary>
/// Move from a position in a list to the end of another list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="positionFrom">position</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Move<TProp>(
Expression<Func<TModel, IList<TProp>>> from,
int positionFrom,
Expression<Func<TModel, IList<TProp>>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"move",
GetPath(path, "-"),
GetPath(from, positionFrom.ToString())));
return this;
}
/// <summary>
/// Move to the end of a list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Move<TProp>(
Expression<Func<TModel, TProp>> from,
Expression<Func<TModel, IList<TProp>>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"move",
GetPath(path, "-"),
GetPath(from, null)));
return this;
}
/// <summary>
/// Copy the value at specified location to the target location. Will result in, for example:
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
/// </summary>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Copy<TProp>(
Expression<Func<TModel, TProp>> from,
Expression<Func<TModel, TProp>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"copy",
GetPath(path, null),
GetPath(from, null)));
return this;
}
/// <summary>
/// Copy from a position in a list to a new location
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="positionFrom">position</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Copy<TProp>(
Expression<Func<TModel, IList<TProp>>> from,
int positionFrom,
Expression<Func<TModel, TProp>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"copy",
GetPath(path, null),
GetPath(from, positionFrom.ToString())));
return this;
}
/// <summary>
/// Copy from a property to a location in a list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <param name="positionTo">position</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Copy<TProp>(
Expression<Func<TModel, TProp>> from,
Expression<Func<TModel, IList<TProp>>> path,
int positionTo)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"copy",
GetPath(path, positionTo.ToString()),
GetPath(from, null)));
return this;
}
/// <summary>
/// Copy from a position in a list to a new location in a list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="positionFrom">position (source)</param>
/// <param name="path">target location</param>
/// <param name="positionTo">position (target)</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Copy<TProp>(
Expression<Func<TModel, IList<TProp>>> from,
int positionFrom,
Expression<Func<TModel, IList<TProp>>> path,
int positionTo)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"copy",
GetPath(path, positionTo.ToString()),
GetPath(from, positionFrom.ToString())));
return this;
}
/// <summary>
/// Copy from a position in a list to the end of another list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="positionFrom">position</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Copy<TProp>(
Expression<Func<TModel, IList<TProp>>> from,
int positionFrom,
Expression<Func<TModel, IList<TProp>>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"copy",
GetPath(path, "-"),
GetPath(from, positionFrom.ToString())));
return this;
}
/// <summary>
/// Copy to the end of a list
/// </summary>
/// <typeparam name="TProp"></typeparam>
/// <param name="from">source location</param>
/// <param name="path">target location</param>
/// <returns></returns>
public JsonPatchDocument<TModel> Copy<TProp>(
Expression<Func<TModel, TProp>> from,
Expression<Func<TModel, IList<TProp>>> path)
{
if (from == null)
{
throw new ArgumentNullException(nameof(from));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Operations.Add(new Operation<TModel>(
"copy",
GetPath(path, "-"),
GetPath(from, null)));
return this;
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
public void ApplyTo(TModel objectToApplyTo)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, null, new AdapterFactory()));
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
/// <param name="logErrorAction">Action to log errors</param>
public void ApplyTo(TModel objectToApplyTo, Action<JsonPatchError> logErrorAction)
{
ApplyTo(objectToApplyTo, new ObjectAdapter(ContractResolver, logErrorAction, new AdapterFactory()), logErrorAction);
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
/// <param name="adapter">IObjectAdapter instance to use when applying</param>
/// <param name="logErrorAction">Action to log errors</param>
public void ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter, Action<JsonPatchError> logErrorAction)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}
foreach (var op in Operations)
{
try
{
op.Apply(objectToApplyTo, adapter);
}
catch (JsonPatchException jsonPatchException)
{
var errorReporter = logErrorAction ?? ErrorReporter.Default;
errorReporter(new JsonPatchError(objectToApplyTo, op, jsonPatchException.Message));
// As per JSON Patch spec if an operation results in error, further operations should not be executed.
break;
}
}
}
/// <summary>
/// Apply this JsonPatchDocument
/// </summary>
/// <param name="objectToApplyTo">Object to apply the JsonPatchDocument to</param>
/// <param name="adapter">IObjectAdapter instance to use when applying</param>
public void ApplyTo(TModel objectToApplyTo, IObjectAdapter adapter)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}
// apply each operation in order
foreach (var op in Operations)
{
op.Apply(objectToApplyTo, adapter);
}
}
IList<Operation> IJsonPatchDocument.GetOperations()
{
var allOps = new List<Operation>();
if (Operations != null)
{
foreach (var op in Operations)
{
var untypedOp = new Operation
{
op = op.op,
value = op.value,
path = op.path,
from = op.from
};
allOps.Add(untypedOp);
}
}
return allOps;
}
// Internal for testing
internal string GetPath<TProp>(Expression<Func<TModel, TProp>> expr, string position)
{
var segments = GetPathSegments(expr.Body);
var path = String.Join("/", segments);
if (position != null)
{
path += "/" + position;
if (segments.Count == 0)
{
return path;
}
}
return "/" + path;
}
private List<string> GetPathSegments(Expression expr)
{
var listOfSegments = new List<string>();
switch (expr.NodeType)
{
case ExpressionType.ArrayIndex:
var binaryExpression = (BinaryExpression)expr;
listOfSegments.AddRange(GetPathSegments(binaryExpression.Left));
listOfSegments.Add(binaryExpression.Right.ToString());
return listOfSegments;
case ExpressionType.Call:
var methodCallExpression = (MethodCallExpression)expr;
listOfSegments.AddRange(GetPathSegments(methodCallExpression.Object));
listOfSegments.Add(EvaluateExpression(methodCallExpression.Arguments[0]));
return listOfSegments;
case ExpressionType.Convert:
listOfSegments.AddRange(GetPathSegments(((UnaryExpression)expr).Operand));
return listOfSegments;
case ExpressionType.MemberAccess:
var memberExpression = expr as MemberExpression;
listOfSegments.AddRange(GetPathSegments(memberExpression.Expression));
// Get property name, respecting JsonProperty attribute
listOfSegments.Add(GetPropertyNameFromMemberExpression(memberExpression));
return listOfSegments;
case ExpressionType.Parameter:
// Fits "x => x" (the whole document which is "" as JSON pointer)
return listOfSegments;
default:
throw new InvalidOperationException(Resources.FormatExpressionTypeNotSupported(expr));
}
}
private string GetPropertyNameFromMemberExpression(MemberExpression memberExpression)
{
var jsonObjectContract = ContractResolver.ResolveContract(memberExpression.Expression.Type) as JsonObjectContract;
if (jsonObjectContract != null)
{
return jsonObjectContract.Properties
.First(jsonProperty => jsonProperty.UnderlyingName == memberExpression.Member.Name)
.PropertyName;
}
return null;
}
private static bool ContinueWithSubPath(ExpressionType expressionType)
{
return (expressionType == ExpressionType.ArrayIndex
|| expressionType == ExpressionType.Call
|| expressionType == ExpressionType.Convert
|| expressionType == ExpressionType.MemberAccess);
}
// Evaluates the value of the key or index which may be an int or a string,
// or some other expression type.
// The expression is converted to a delegate and the result of executing the delegate is returned as a string.
private static string EvaluateExpression(Expression expression)
{
var converted = Expression.Convert(expression, typeof(object));
var fakeParameter = Expression.Parameter(typeof(object), null);
var lambda = Expression.Lambda<Func<object, object>>(converted, fakeParameter);
var func = lambda.Compile();
return Convert.ToString(func(null), CultureInfo.InvariantCulture);
}
}
}

View File

@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Operations;
namespace Microsoft.AspNetCore.JsonPatch
{
/// <summary>
/// Captures error message and the related entity and the operation that caused it.
/// </summary>
public class JsonPatchError
{
/// <summary>
/// Initializes a new instance of <see cref="JsonPatchError"/>.
/// </summary>
/// <param name="affectedObject">The object that is affected by the error.</param>
/// <param name="operation">The <see cref="Operation"/> that caused the error.</param>
/// <param name="errorMessage">The error message.</param>
public JsonPatchError(
object affectedObject,
Operation operation,
string errorMessage)
{
if (errorMessage == null)
{
throw new ArgumentNullException(nameof(errorMessage));
}
AffectedObject = affectedObject;
Operation = operation;
ErrorMessage = errorMessage;
}
/// <summary>
/// Gets the object that is affected by the error.
/// </summary>
public object AffectedObject { get; }
/// <summary>
/// Gets the <see cref="Operation"/> that caused the error.
/// </summary>
public Operation Operation { get; }
/// <summary>
/// Gets the error message.
/// </summary>
public string ErrorMessage { get; }
}
}

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core support for JSON PATCH.</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;json;jsonpatch</PackageTags>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json" />
<Reference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,82 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Adapters;
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.JsonPatch.Operations
{
public class Operation : OperationBase
{
[JsonProperty("value")]
public object value { get; set; }
public Operation()
{
}
public Operation(string op, string path, string from, object value)
: base(op, path, from)
{
this.value = value;
}
public Operation(string op, string path, string from)
: base(op, path, from)
{
}
public void Apply(object objectToApplyTo, IObjectAdapter adapter)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}
switch (OperationType)
{
case OperationType.Add:
adapter.Add(this, objectToApplyTo);
break;
case OperationType.Remove:
adapter.Remove(this, objectToApplyTo);
break;
case OperationType.Replace:
adapter.Replace(this, objectToApplyTo);
break;
case OperationType.Move:
adapter.Move(this, objectToApplyTo);
break;
case OperationType.Copy:
adapter.Copy(this, objectToApplyTo);
break;
case OperationType.Test:
if (adapter is IObjectAdapterWithTest adapterWithTest)
{
adapterWithTest.Test(this, objectToApplyTo);
break;
}
else
{
throw new NotSupportedException(Resources.TestOperationNotSupported);
}
default:
break;
}
}
public bool ShouldSerializevalue()
{
return (OperationType == OperationType.Add
|| OperationType == OperationType.Replace
|| OperationType == OperationType.Test);
}
}
}

View File

@ -0,0 +1,76 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Newtonsoft.Json;
namespace Microsoft.AspNetCore.JsonPatch.Operations
{
public class OperationBase
{
private string _op;
private OperationType _operationType;
[JsonIgnore]
public OperationType OperationType
{
get
{
return _operationType;
}
}
[JsonProperty("path")]
public string path { get; set; }
[JsonProperty("op")]
public string op
{
get
{
return _op;
}
set
{
OperationType result;
if (!Enum.TryParse(value, ignoreCase: true, result: out result))
{
result = OperationType.Invalid;
}
_operationType = result;
_op = value;
}
}
[JsonProperty("from")]
public string from { get; set; }
public OperationBase()
{
}
public OperationBase(string op, string path, string from)
{
if (op == null)
{
throw new ArgumentNullException(nameof(op));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
this.op = op;
this.path = path;
this.from = from;
}
public bool ShouldSerializefrom()
{
return (OperationType == OperationType.Move
|| OperationType == OperationType.Copy);
}
}
}

View File

@ -0,0 +1,94 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.JsonPatch.Adapters;
using Microsoft.AspNetCore.JsonPatch.Exceptions;
namespace Microsoft.AspNetCore.JsonPatch.Operations
{
public class Operation<TModel> : Operation where TModel : class
{
public Operation()
{
}
public Operation(string op, string path, string from, object value)
: base(op, path, from)
{
if (op == null)
{
throw new ArgumentNullException(nameof(op));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
this.value = value;
}
public Operation(string op, string path, string from)
: base(op, path, from)
{
if (op == null)
{
throw new ArgumentNullException(nameof(op));
}
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
}
public void Apply(TModel objectToApplyTo, IObjectAdapter adapter)
{
if (objectToApplyTo == null)
{
throw new ArgumentNullException(nameof(objectToApplyTo));
}
if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}
switch (OperationType)
{
case OperationType.Add:
adapter.Add(this, objectToApplyTo);
break;
case OperationType.Remove:
adapter.Remove(this, objectToApplyTo);
break;
case OperationType.Replace:
adapter.Replace(this, objectToApplyTo);
break;
case OperationType.Move:
adapter.Move(this, objectToApplyTo);
break;
case OperationType.Copy:
adapter.Copy(this, objectToApplyTo);
break;
case OperationType.Test:
if (adapter is IObjectAdapterWithTest adapterWithTest)
{
adapterWithTest.Test(this, objectToApplyTo);
break;
}
else
{
throw new JsonPatchException(new JsonPatchError(objectToApplyTo, this, Resources.TestOperationNotSupported));
}
case OperationType.Invalid:
throw new JsonPatchException(
Resources.FormatInvalidJsonPatchOperation(op), innerException: null);
default:
break;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More