This commit is contained in:
Matt Fei 2017-03-20 13:44:33 -07:00
Коммит 27249c63ee
33 изменённых файлов: 2314 добавлений и 0 удалений

52
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,52 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.resx text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto
*.vbproj text=auto
*.fsproj text=auto
*.dbproj text=auto
*.sln text=auto eol=crlf
*.sh eol=lf

15
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
[Oo]bj/
[Bb]in/
TestResults/
_ReSharper.*/
/packages/
artifacts/
PublishProfiles/
*.user
*.suo
*.cache
*.sln.ide
.vs
.build/
.testPublish/
msbuild.*

14
.nuget/NuGet.Config Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="Mygit" value="https://dotnet.myget.org/F/dotnet-core/api/v3/" />
</packageSources>
<packageRestore>
<!-- Disables command-line, automatic, and MSBuild-Integrated restore -->
<add key="enabled" value="True" />
</packageRestore>
</configuration>

Двоичные данные
.nuget/NuGet.exe Normal file

Двоичный файл не отображается.

144
.nuget/NuGet.targets Normal file
Просмотреть файл

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
<!-- Property that enables building a package from a project -->
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
<!-- Download NuGet.exe if it does not already exist -->
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://www.nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
</PropertyGroup>
<PropertyGroup>
<PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>
<PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
</PropertyGroup>
<PropertyGroup>
<PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
<PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet command -->
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
RestorePackages;
$(BuildDependsOn);
</BuildDependsOn>
<!-- Make the build depend on restore packages -->
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
$(BuildDependsOn);
BuildPackage;
</BuildDependsOn>
</PropertyGroup>
<Target Name="CheckPrerequisites">
<!-- Raise an error if we're unable to locate nuget.exe -->
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
<!--
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
This effectively acts as a lock that makes sure that the download operation will only happen once and all
parallel builds will have to wait for it to complete.
-->
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
</Target>
<Target Name="_DownloadNuGet">
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)"
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(BuildCommand)"
Condition=" '$(OS)' != 'Windows_NT' " />
<Exec Command="$(BuildCommand)"
LogStandardErrorAsError="true"
Condition=" '$(OS)' == 'Windows_NT' " />
</Target>
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<OutputFilename ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Net" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
OutputFilename = Path.GetFullPath(OutputFilename);
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>

30
Build.cmd Normal file
Просмотреть файл

@ -0,0 +1,30 @@
@ECHO OFF
setlocal
set EnableNuGetPackageRestore=true
set logOptions=/flp:Summary;Verbosity=detailed;LogFile=msbuild.log /flp1:warningsonly;logfile=msbuild.wrn /flp2:errorsonly;logfile=msbuild.err
REM Find the most recent 32bit MSBuild.exe on the system. Require v12.0 (installed with VS2013) or later since .NET 4.0
REM is not supported. Always quote the %MSBuild% value when setting the variable and never quote %MSBuild% references.
set MSBuild="%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe"
if not exist %MSBuild% @set MSBuild="%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe"
if not exist %MSBuild% (
echo Could not find msbuild.exe. Please run this from a Visual Studio developer prompt
goto BuildFail
)
%MSBuild% "%~dp0\Microsoft.AspNet.CorrelationActivity.msbuild" %logOptions% /v:minimal /maxcpucount /nodeReuse:false %*
if %ERRORLEVEL% neq 0 goto BuildFail
goto BuildSuccess
:BuildFail
echo.
echo *** BUILD FAILED ***
exit /B 999
:BuildSuccess
echo.
echo **** BUILD SUCCESSFUL ***
exit /B 0

Просмотреть файл

@ -0,0 +1,51 @@
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="tools\Microsoft.AspNet.CorrelationActivity.settings.targets"/>
<ItemGroup>
<AssemblyProject Include="src\Microsoft.AspNet.CorrelationActivity\Microsoft.AspNet.CorrelationActivity.csproj" />
</ItemGroup>
<ItemGroup>
<AssemblyProject Include="test\Microsoft.AspNet.CorrelationActivity.Tests\Microsoft.AspNet.CorrelationActivity.Tests.csproj" />
</ItemGroup>
<ItemGroup>
<PackageProject Include="src\Packages\Packages.csproj" />
</ItemGroup>
<!-- Composite targets -->
<Target Name="BuildCI" DependsOnTargets="Clean;Build" />
<Target Name="Build" DependsOnTargets="BuildAssemblies;BuildPackages" />
<Target Name="Clean" DependsOnTargets="CleanPackages;CleanAssemblies" />
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
<!-- Core build-->
<Target Name="BuildAssemblies" DependsOnTargets="RestorePackages">
<MSBuild Targets="Build" Projects="@(AssemblyProject)" />
</Target>
<Target Name="CleanAssemblies">
<MSBuild Targets="Clean" Projects="@(AssemblyProject)" />
</Target>
<Target Name="RebuildAssemblies" DependsOnTargets="Clean;Build" />
<!-- Packages build -->
<Target Name="BuildPackages" DependsOnTargets="RestorePackages">
<MSBuild Targets="" Projects="@(PackageProject)" />
</Target>
<Target Name="CleanPackages">
<MSBuild Targets="Clean" Projects="@(PackageProject)" />
</Target>
<Target Name="RebuildPackages" DependsOnTargets="CleanPackages;BuildPackages" />
<Target Name="RestorePackages">
<Exec Command=".nuget\NuGet.exe restore" />
</Target>
<Import Project="tools\Microsoft.AspNet.CorrelationActivity.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{258D5057-81B9-40EC-A872-D21E27452749}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.CorrelationActivity", "src\Microsoft.AspNet.CorrelationActivity\Microsoft.AspNet.CorrelationActivity.csproj", "{4C8E592C-C532-4CF2-80EF-3BDD0D788D12}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.CorrelationActivity.Tests", "test\Microsoft.AspNet.CorrelationActivity.Tests\Microsoft.AspNet.CorrelationActivity.Tests.csproj", "{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4C8E592C-C532-4CF2-80EF-3BDD0D788D12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C8E592C-C532-4CF2-80EF-3BDD0D788D12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C8E592C-C532-4CF2-80EF-3BDD0D788D12}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C8E592C-C532-4CF2-80EF-3BDD0D788D12}.Release|Any CPU.Build.0 = Release|Any CPU
{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4C8E592C-C532-4CF2-80EF-3BDD0D788D12} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED} = {258D5057-81B9-40EC-A872-D21E27452749}
EndGlobalSection
EndGlobal

Двоичные данные
src/35MSSharedLib1024.snk Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.AspNet.CorrelationActivity
{
/// <summary>
/// Extensions of Activity class
/// </summary>
internal static class ActivityExtensions
{
public const string RequestIDHeaderName = "Request-Id";
public const string CorrelationContextHeaderName = "Correlation-Context";
/// <summary>
/// Read activity information from HTTP request header and restore them to the activity
/// </summary>
/// <param name="activity"></param>
/// <param name="requestHeaders"></param>
public static void RestoreActivityInfoFromRequestHeaders(this Activity activity, NameValueCollection requestHeaders)
{
var requestIDs = requestHeaders.GetValues(RequestIDHeaderName);
if (requestIDs != null)
{
try
{
// there may be several Request-Id header, but we only read the first one
activity.SetParentId(requestIDs[0]);
// Header format - Correlation-Context: key1=value1, key2=value2
var baggages = requestHeaders.GetValues(CorrelationContextHeaderName);
if (baggages != null)
{
// there may be several Correlation-Context header
foreach (var item in baggages)
{
foreach(var pair in item.Split(','))
{
NameValueHeaderValue baggageItem;
if (NameValueHeaderValue.TryParse(pair, out baggageItem))
{
try
{
activity.AddBaggage(baggageItem.Name, baggageItem.Value);
}
catch (ArgumentException)
{ }
}
}
}
}
}
catch (ArgumentException)
{ }
}
}
}
}

Просмотреть файл

@ -0,0 +1,113 @@
using System;
using System.Diagnostics;
using System.Web;
namespace Microsoft.AspNet.CorrelationActivity
{
/// <summary>
/// Activity helper class
/// </summary>
internal static class ActivityHelper
{
public const string AspNetListenerName = "Microsoft.AspNet.Correlation";
public const string AspNetActivityName = "Microsoft.AspNet.Activity";
public const string AspNetActivityStartName = "Microsoft.AspNet.Activity.Start";
public const string AspNetExceptionActivityName = "Microsoft.AspNet.Activity.Exception";
public const string ActivityKey = "__AspnetActivity__";
private static DiagnosticListener s_aspNetListener = new DiagnosticListener(AspNetListenerName);
/// <summary>
/// It's possible that a request is executed in both native threads and managed threads,
/// in such case Activity.Current will be lost during native thread and managed thread swtich.
/// This method is intended to restore the current activity in order to correlate the child
/// activities with the root activity of the request.
/// </summary>
/// <returns>If it returns an activity, the dev is responsible for stopping it</returns>
public static Activity RestoreCurrentActivity(HttpContextBase context)
{
if(Activity.Current != null || context == null ||
context.Items[ActivityKey] as Activity == null)
{
return null;
}
// workaround to restore the root activity, because we don't
// have a way to change the Activity.Current
var root = (Activity)context.Items[ActivityKey];
var childActivity = new Activity(root.OperationName);
childActivity.SetParentId(root.Id);
foreach(var item in root.Baggage)
{
childActivity.AddBaggage(item.Key, item.Value);
}
childActivity.Start();
return childActivity;
}
/// <summary>
/// To stop the activity that dev gets from RestoreCurrentActivity
/// </summary>
/// <param name="activity"></param>
/// <param name="context"></param>
public static void StopAspNetActivity(Activity activity, object context)
{
if (activity != null)
{
s_aspNetListener.StopActivity(activity, context);
}
}
public static Activity CreateRootActivity(HttpContextBase context)
{
Activity rootActivity = null;
if (s_aspNetListener.IsEnabled() && s_aspNetListener.IsEnabled(AspNetActivityName))
{
rootActivity = new Activity(ActivityHelper.AspNetActivityName);
rootActivity.RestoreActivityInfoFromRequestHeaders(context.Request.Headers);
StartAspNetActivity(rootActivity, new { Context = context });
SaveCurrentActivity(context, rootActivity);
}
return rootActivity;
}
public static void TriggerAspNetExceptionActivity(Exception ex)
{
if(s_aspNetListener.IsEnabled() && s_aspNetListener.IsEnabled(AspNetExceptionActivityName))
{
s_aspNetListener.Write(AspNetExceptionActivityName, new { ActivityException = ex });
}
}
private static void StartAspNetActivity(Activity activity, object context)
{
if (s_aspNetListener.IsEnabled(AspNetActivityName, activity, context))
{
if (s_aspNetListener.IsEnabled(AspNetActivityStartName))
{
s_aspNetListener.StartActivity(activity, context);
}
else
{
activity.Start();
}
}
}
/// <summary>
/// This should be called after the Activity starts
/// and only for root activity of a request
/// </summary>
private static void SaveCurrentActivity(HttpContextBase context, Activity activity)
{
Debug.Assert(context != null);
Debug.Assert(activity != null);
Debug.Assert(context.Items[ActivityKey] == null);
context.Items[ActivityKey] = activity;
}
}
}

Просмотреть файл

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Microsoft.AspNet.CorrelationActivity
{
class ActivityTrackingModule : IHttpModule
{
private Activity _activity;
private Activity _rootActivityInHandlerExecution;
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += Application_BeginRequest;
context.EndRequest += Application_EndRequest;
context.PreRequestHandlerExecute += Application_PreRequestHandlerExecute;
context.PostRequestHandlerExecute += Application_PostRequestHandlerExecute;
context.Error += Application_Error;
}
private HttpContextBase CurrentHttpContext
{
get
{
HttpContextWrapper context = null;
if (HttpContext.Current != null)
{
context = new HttpContextWrapper(HttpContext.Current);
}
return context;
}
}
private void Application_BeginRequest(object sender, EventArgs e)
{
_activity = ActivityHelper.CreateRootActivity(CurrentHttpContext);
}
private void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
_rootActivityInHandlerExecution = ActivityHelper.RestoreCurrentActivity(CurrentHttpContext);
}
private void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
ActivityHelper.StopAspNetActivity(_rootActivityInHandlerExecution, new { Context = CurrentHttpContext });
}
private void Application_Error(object sender, EventArgs e)
{
// In case unhandled exception is thrown before PreRequestHandlerExecute
var currentActivity = ActivityHelper.RestoreCurrentActivity(CurrentHttpContext);
var app = (HttpApplication)sender;
ActivityHelper.TriggerAspNetExceptionActivity(app.Server.GetLastError());
ActivityHelper.StopAspNetActivity(currentActivity, new { Context = CurrentHttpContext });
// In case unhandled exception is thrown during handler executing, which won't
// trigger PostRequestHandlerExecut event.
ActivityHelper.StopAspNetActivity(_rootActivityInHandlerExecution, new { Context = CurrentHttpContext });
}
private void Application_EndRequest(object sender, EventArgs e)
{
ActivityHelper.StopAspNetActivity(_activity, new { Context = CurrentHttpContext });
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Microsoft.AspNet.CorrelationActivity.sln))\tools\Microsoft.AspNet.CorrelationActivity.settings.targets" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4C8E592C-C532-4CF2-80EF-3BDD0D788D12}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.AspNet.CorrelationActivity</RootNamespace>
<AssemblyName>Microsoft.AspNet.CorrelationActivity</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<DelaySign>true</DelaySign>
<AssemblyOriginatorKeyFile>..\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<DocumentationFile>$(OutputPath)$(AssemblyName).xml</DocumentationFile>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Diagnostics.DiagnosticSource.4.4.0-beta-25114-01\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ActivityExtensions.cs" />
<Compile Include="ActivityHelper.cs" />
<Compile Include="ActivityTrackingModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Microsoft.AspNet.CorrelationActivity</name>
</assembly>
<members>
<member name="T:Microsoft.AspNet.CorrelationActivity.ActivityExtensions">
<summary>
Extensions of Activity class
</summary>
</member>
<member name="M:Microsoft.AspNet.CorrelationActivity.ActivityExtensions.RestoreActivityInfoFromRequestHeaders(System.Diagnostics.Activity,System.Collections.Specialized.NameValueCollection)">
<summary>
Read activity information from HTTP request header and restore them to the activity
</summary>
<param name="activity"></param>
<param name="requestHeaders"></param>
</member>
<member name="T:Microsoft.AspNet.CorrelationActivity.ActivityHelper">
<summary>
Activity helper class
</summary>
</member>
<member name="M:Microsoft.AspNet.CorrelationActivity.ActivityHelper.RestoreCurrentActivity(System.Web.HttpContextBase)">
<summary>
It's possible that a request is executed in both native threads and managed threads,
in such case Activity.Current will be lost during native thread and managed thread swtich.
This method is intended to restore the current activity in order to correlate the child
activities with the root activity of the request.
</summary>
<returns>If it returns an activity, the dev is responsible for stopping it</returns>
</member>
<member name="M:Microsoft.AspNet.CorrelationActivity.ActivityHelper.StopAspNetActivity(System.Diagnostics.Activity,System.Object)">
<summary>
To stop the activity that dev gets from RestoreCurrentActivity
</summary>
<param name="activity"></param>
<param name="context"></param>
</member>
<member name="M:Microsoft.AspNet.CorrelationActivity.ActivityHelper.SaveCurrentActivity(System.Web.HttpContextBase,System.Diagnostics.Activity)">
<summary>
This should be called after the Activity starts
and only for root activity of a request
</summary>
</member>
</members>
</doc>

Просмотреть файл

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Microsoft.AspNet.CorrelationActivity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyProduct("Microsoft.AspNet.CorrelationActivity")]
[assembly: AssemblyCopyright("\x00a9 Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4c8e592c-c532-4cf2-80ef-3bdd0d788d12")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: InternalsVisibleTo("Microsoft.AspNet.CorrelationActivity.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]

Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Diagnostics.DiagnosticSource" version="4.4.0-beta-25114-01" targetFramework="net46" />
</packages>

Просмотреть файл

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Microsoft.AspNet.CorrelationActivity.sln))\tools\Microsoft.AspNet.CorrelationActivity.settings.targets" />
<PropertyGroup>
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
<NuGetPackageId>$(MSBuildProjectName)</NuGetPackageId>
<NuSpecFile>$(MSBuildProjectName).nuspec</NuSpecFile>
</PropertyGroup>
<ItemGroup>
<NuGetContent Include="$(AssemblyName).dll">
<Source>$(AssemblyPath)</Source>
<Destination>lib\net46</Destination>
</NuGetContent>
<NuGetContent Include="$(AssemblyName).xml">
<Source>$(OutputPath)</Source>
<Destination>lib\net46</Destination>
</NuGetContent>
<NuGetContent Include="$(AssemblyName).pdb" Condition="'$(NuGetPackSymbols)' == 'true'">
<Source>$(OutputPath)</Source>
<Destination>lib\net46</Destination>
</NuGetContent>
<NuGetContentProject Include="$(RepositoryRoot)\src\$(MSBuildProjectName)\$(MSBuildProjectName).csproj" Condition="'$(NuGetPackSymbols)' == 'true'" />
<NuGetContent Include="content\net46\*">
<Destination>content\net46</Destination>
</NuGetContent>
</ItemGroup>
<Import Project="$(RepositoryRoot)Tools\NuGetProj.targets"/>
</Project>

Просмотреть файл

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>$NuGetPackageId$</id>
<title>Microsoft.AspNet.CorrelationActivity</title>
<version>$NuGetPackageVersion$</version>
<authors>Microsoft</authors>
<owners>Microsoft</owners>
<copyright>&#169; Microsoft Corporation. All rights reserved.</copyright>
<description>Provides a module to support correlation activity usage in asp.net applications.</description>
<summary>Provides a module to support correlation activity usage in asp.net applications.</summary>
<language>en-US</language>
<projectUrl>http://www.asp.net/</projectUrl>
<licenseUrl>http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<tags>DiagnosticSource Correlation Activity ASP.NET</tags>
<dependencies>
<dependency id="System.Diagnostics.DiagnosticSource" version="$DiagnosticSourceNuGetPackageVersion$" />
</dependencies>
</metadata>
</package>

Просмотреть файл

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer xdt:Transform="InsertIfMissing">
<modules xdt:Transform="InsertIfMissing">
</modules>
</system.webServer>
<system.webServer>
<modules>
<add name="ActivityTrackingModule"
type="Microsoft.AspNet.CorrelationActivity.ActivityTrackingModule, Microsoft.AspNet.CorrelationActivity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
preCondition="integratedMode,managedHandler" xdt:Transform="Insert" />
</modules>
</system.webServer>
</configuration>

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<modules>
<add name="ActivityTrackingModule"
type="Microsoft.AspNet.CorrelationActivity.ActivityTrackingModule, Microsoft.AspNet.CorrelationActivity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
preCondition="integratedMode,managedHandler" xdt:Transform="Remove" xdt:Locator="Match(type)" />
</modules>
</system.webServer>
</configuration>

Просмотреть файл

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Microsoft.AspNet.CorrelationActivity.sln))\tools\Microsoft.AspNet.CorrelationActivity.settings.targets" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SkipCopyBuildProduct>true</SkipCopyBuildProduct>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7EC5863F-7FF1-41C7-A384-8FFF81531E7A}</ProjectGuid>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
<ItemGroup>
<NuGetProject Include="Microsoft.AspNet.CorrelationActivity\Microsoft.AspNet.CorrelationActivity.nuproj" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="Build">
<MSBuild Projects="@(NuGetProject)" Targets="Build" />
</Target>
<Target Name="Clean">
<MSBuild Projects="@(NuGetProject)" Targets="Clean" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project>

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNet.CorrelationActivity.Tests
{
public class ActivityExtensionsTest
{
private const string TestActivityName = "Activity.Test";
[Fact]
public void Restore_Nothing_If_Header_Does_Not_Contain_RequestId()
{
var activity = new Activity(TestActivityName);
var requestHeaders = new NameValueCollection();
activity.RestoreActivityInfoFromRequestHeaders(requestHeaders);
Assert.True(string.IsNullOrEmpty(activity.ParentId));
Assert.Empty(activity.Baggage);
}
[Fact]
public void Can_Restore_First_RequestId_When_Multiple_RequestId_In_Headers()
{
var activity = new Activity(TestActivityName);
var requestHeaders = new NameValueCollection();
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "/aba2f1e978b11111.1");
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "/aba2f1e978b22222.1");
activity.RestoreActivityInfoFromRequestHeaders(requestHeaders);
Assert.Equal("/aba2f1e978b11111.1", activity.ParentId);
Assert.Empty(activity.Baggage);
}
[Fact]
public void Restore_Empty_RequestId_Should_Not_Throw_Exception()
{
var activity = new Activity(TestActivityName);
var requestHeaders = new NameValueCollection();
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "");
activity.RestoreActivityInfoFromRequestHeaders(requestHeaders);
Assert.True(string.IsNullOrEmpty(activity.ParentId));
Assert.Empty(activity.Baggage);
}
[Fact]
public void Can_Restore_Baggages_When_CorrelationContext_In_Headers()
{
var activity = new Activity(TestActivityName);
var requestHeaders = new NameValueCollection();
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "/aba2f1e978b11111.1");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key1=123,key2=456,key3=789");
activity.RestoreActivityInfoFromRequestHeaders(requestHeaders);
Assert.Equal("/aba2f1e978b11111.1", activity.ParentId);
var baggageItems = new List<KeyValuePair<string, string>>();
baggageItems.Add(new KeyValuePair<string, string>("key1", "123"));
baggageItems.Add(new KeyValuePair<string, string>("key2", "456"));
baggageItems.Add(new KeyValuePair<string, string>("key3", "789"));
var expectedBaggage = baggageItems.OrderBy(kvp => kvp.Key);
var actualBaggage = activity.Baggage.OrderBy(kvp => kvp.Key);
Assert.Equal(expectedBaggage, actualBaggage);
}
[Fact]
public void Can_Restore_Baggages_When_Multiple_CorrelationContext_In_Headers()
{
var activity = new Activity(TestActivityName);
var requestHeaders = new NameValueCollection();
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "/aba2f1e978b11111.1");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key1=123,key2=456,key3=789");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key4=abc,key5=def");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key6=xyz");
activity.RestoreActivityInfoFromRequestHeaders(requestHeaders);
Assert.Equal("/aba2f1e978b11111.1", activity.ParentId);
var baggageItems = new List<KeyValuePair<string, string>>();
baggageItems.Add(new KeyValuePair<string, string>("key1", "123"));
baggageItems.Add(new KeyValuePair<string, string>("key2", "456"));
baggageItems.Add(new KeyValuePair<string, string>("key3", "789"));
baggageItems.Add(new KeyValuePair<string, string>("key4", "abc"));
baggageItems.Add(new KeyValuePair<string, string>("key5", "def"));
baggageItems.Add(new KeyValuePair<string, string>("key6", "xyz"));
var expectedBaggage = baggageItems.OrderBy(kvp => kvp.Key);
var actualBaggage = activity.Baggage.OrderBy(kvp => kvp.Key);
Assert.Equal(expectedBaggage, actualBaggage);
}
[Fact]
public void Can_Restore_Baggages_When_Some_MalFormat_CorrelationContext_In_Headers()
{
var activity = new Activity(TestActivityName);
var requestHeaders = new NameValueCollection();
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "/aba2f1e978b11111.1");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key1=123,key2=456,key3=789");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key4=abc;key5=def");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, "key6????xyz");
activity.RestoreActivityInfoFromRequestHeaders(requestHeaders);
Assert.Equal("/aba2f1e978b11111.1", activity.ParentId);
var baggageItems = new List<KeyValuePair<string, string>>();
baggageItems.Add(new KeyValuePair<string, string>("key1", "123"));
baggageItems.Add(new KeyValuePair<string, string>("key2", "456"));
baggageItems.Add(new KeyValuePair<string, string>("key3", "789"));
var expectedBaggage = baggageItems.OrderBy(kvp => kvp.Key);
var actualBaggage = activity.Baggage.OrderBy(kvp => kvp.Key);
Assert.Equal(expectedBaggage, actualBaggage);
}
}
}

Просмотреть файл

@ -0,0 +1,324 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Xunit;
namespace Microsoft.AspNet.CorrelationActivity.Tests
{
public class ActivityHelperTest
{
private const string TestActivityName = "Activity.Test";
private List<KeyValuePair<string, string>> _baggageItems = new List<KeyValuePair<string, string>>();
private string _baggageInHeader;
public ActivityHelperTest()
{
_baggageItems.Add(new KeyValuePair<string, string>("TestKey1", "123"));
_baggageItems.Add(new KeyValuePair<string, string>("TestKey2", "456"));
_baggageItems.Add(new KeyValuePair<string, string>("TestKey1", "789"));
_baggageInHeader = "TestKey1=123,TestKey2=456,TestKey1=789";
// reset static fields
var allListenerField = typeof(DiagnosticListener).
GetField("s_allListenerObservable", BindingFlags.Static | BindingFlags.NonPublic);
allListenerField.SetValue(null, null);
var aspnetListenerField = typeof(ActivityHelper).
GetField("s_aspNetListener", BindingFlags.Static | BindingFlags.NonPublic);
aspnetListenerField.SetValue(null, new DiagnosticListener(ActivityHelper.AspNetListenerName));
}
#region RestoreCurrentActivity tests
[Fact]
public void Should_Not_Restore_If_ActivityCurrent_Is_Available()
{
var rootActivity = CreateActivity();
var context = CreateHttpContext();
rootActivity.Start();
var restoredActivity = ActivityHelper.RestoreCurrentActivity(context);
Assert.Null(restoredActivity);
}
[Fact]
public void Should_Not_Restore_If_HttpContext_Is_Not_Available()
{
var restoredActivity = ActivityHelper.RestoreCurrentActivity(null);
Assert.Null(restoredActivity);
}
[Fact]
public void Should_Not_Restore_If_Root_Activity_Is_Not_In_HttpContext()
{
var context = CreateHttpContext();
var restoredActivity = ActivityHelper.RestoreCurrentActivity(context);
Assert.Null(restoredActivity);
}
[Fact]
public void Can_Restore_Activity()
{
var rootActivity = CreateActivity();
rootActivity.Start();
var context = CreateHttpContext();
context.Items[ActivityHelper.ActivityKey] = rootActivity;
ExecutionContext.SuppressFlow();
Task.Run(() =>
{
var restoredActivity = ActivityHelper.RestoreCurrentActivity(context);
Assert.NotNull(restoredActivity);
Assert.True(rootActivity.Id == restoredActivity.ParentId);
Assert.True(!string.IsNullOrEmpty(restoredActivity.Id));
var expectedBaggage = _baggageItems.OrderBy(item => item.Value);
var actualBaggage = rootActivity.Baggage.OrderBy(item => item.Value);
Assert.Equal(expectedBaggage, actualBaggage);
}).Wait();
}
#endregion
#region StopAspNetActivity tests
[Fact]
public void Can_Stop_Activity_Without_AspNetListener_Enabled()
{
var rootActivity = CreateActivity();
rootActivity.Start();
Thread.Sleep(100);
ActivityHelper.StopAspNetActivity(rootActivity, null);
Assert.True(rootActivity.Duration != TimeSpan.Zero);
Assert.Null(rootActivity.Parent);
}
[Fact]
public void Can_Stop_Activity_With_AspNetListener_Enabled()
{
var rootActivity = CreateActivity();
rootActivity.Start();
Thread.Sleep(100);
EnableAspNetListenerOnly();
ActivityHelper.StopAspNetActivity(rootActivity, null);
Assert.True(rootActivity.Duration != TimeSpan.Zero);
Assert.Null(rootActivity.Parent);
}
#endregion
#region CreateRootActivity tests
[Fact]
public void Should_Not_Create_RootActivity_If_AspNetListener_Not_Enabled()
{
var context = CreateHttpContext();
var rootActivity = ActivityHelper.CreateRootActivity(context);
Assert.Null(rootActivity);
}
[Fact]
public void Should_Not_Create_RootActivity_If_AspNetActivity_Not_Enabled()
{
var context = CreateHttpContext();
EnableAspNetListenerOnly();
var rootActivity = ActivityHelper.CreateRootActivity(context);
Assert.Null(rootActivity);
}
[Fact]
public void Can_Create_RootActivity_And_Restore_Info_From_Request_Header()
{
var requestHeaders = new NameValueCollection();
requestHeaders.Add(ActivityExtensions.RequestIDHeaderName, "/aba2f1e978b2cab6.1");
requestHeaders.Add(ActivityExtensions.CorrelationContextHeaderName, _baggageInHeader);
var context = CreateHttpContext(requestHeaders);
EnableAspNetListenerAndActivity();
var rootActivity = ActivityHelper.CreateRootActivity(context);
Assert.NotNull(rootActivity);
Assert.True(rootActivity.ParentId == "/aba2f1e978b2cab6.1");
var expectedBaggage = _baggageItems.OrderBy(item => item.Value);
var actualBaggage = rootActivity.Baggage.OrderBy(item => item.Value);
Assert.Equal(expectedBaggage, actualBaggage);
}
[Fact]
public void Can_Create_RootActivity_And_Start_Activity()
{
var context = CreateHttpContext();
EnableAspNetListenerAndActivity();
var rootActivity = ActivityHelper.CreateRootActivity(context);
Assert.NotNull(rootActivity);
Assert.True(!string.IsNullOrEmpty(rootActivity.Id));
}
[Fact]
public void Can_Create_RootActivity_And_Saved_In_HttContext()
{
var context = CreateHttpContext();
EnableAspNetListenerAndActivity();
var rootActivity = ActivityHelper.CreateRootActivity(context);
Assert.NotNull(rootActivity);
Assert.Same(rootActivity, context.Items[ActivityHelper.ActivityKey]);
}
#endregion
#region TriggerAspNetExceptionActivity tests
[Fact]
public void Should_Not_Trigger_AspNetExceptionActivity_If_AspNetExceptionActivity_Not_Enabled()
{
var activityTrigger = false;
Action<KeyValuePair<string, object>> onNext = kvp => activityTrigger = true;
EnableAspNetListenerAndActivity(onNext);
ActivityHelper.TriggerAspNetExceptionActivity(new Exception("test"));
Assert.True(!activityTrigger);
}
[Fact]
public void Can_Trigger_AspNetExceptionActivity_If_AspNetExceptionActivity_Enabled()
{
object loggedContext = null;
Action<KeyValuePair<string, object>> onNext = kvp => loggedContext = kvp.Value.GetProperty("ActivityException");
EnableAspNetListenerAndActivity(onNext, ActivityHelper.AspNetExceptionActivityName);
var exception = new Exception("test");
ActivityHelper.TriggerAspNetExceptionActivity(exception);
Assert.Same(exception, loggedContext);
}
#endregion
#region Helper methods
private Activity CreateActivity()
{
var activity = new Activity(TestActivityName);
_baggageItems.ForEach(kv => activity.AddBaggage(kv.Key, kv.Value));
return activity;
}
private HttpContextBase CreateHttpContext(NameValueCollection requestHeaders = null)
{
var context = new TestHttpContext();
if (requestHeaders != null)
{
context.Request.Headers.Add(requestHeaders);
}
return context;
}
private void EnableAspNetListenerAndActivity(Action<KeyValuePair<string, object>> onNext = null,
string ActivityName = ActivityHelper.AspNetActivityName)
{
DiagnosticListener.AllListeners.Subscribe(listener =>
{
// if AspNetListener has subscription, then it is enabled
if (listener.Name == ActivityHelper.AspNetListenerName)
{
listener.Subscribe(new TestDiagnosticListener(onNext),
(name, arg1, arg2) => name == ActivityName);
}
});
}
private void EnableAspNetListenerOnly(Action<KeyValuePair<string, object>> onNext = null)
{
DiagnosticListener.AllListeners.Subscribe(listener =>
{
// if AspNetListener has subscription, then it is enabled
if (listener.Name == ActivityHelper.AspNetListenerName)
{
listener.Subscribe(new TestDiagnosticListener(onNext),
activityName => false);
}
});
}
#endregion
#region Helper Class
private class TestDiagnosticListener : IObserver<KeyValuePair<string, object>>
{
Action<KeyValuePair<string, object>> _onNextCallBack;
public TestDiagnosticListener(Action<KeyValuePair<string, object>> onNext)
{
_onNextCallBack = onNext;
}
public void OnCompleted()
{
}
public void OnError(Exception error)
{
}
public void OnNext(KeyValuePair<string, object> value)
{
if(_onNextCallBack != null)
{
_onNextCallBack(value);
}
}
}
private class TestHttpRequest : HttpRequestBase
{
NameValueCollection _headers = new NameValueCollection();
public override NameValueCollection Headers
{
get
{
return _headers;
}
}
}
private class TestHttpResponse : HttpResponseBase
{
}
private class TestHttpContext : HttpContextBase
{
HttpRequestBase _request = new TestHttpRequest();
HttpResponseBase _response = new TestHttpResponse();
Hashtable _items = new Hashtable();
public override HttpRequestBase Request
{
get
{
return _request;
}
}
public override IDictionary Items
{
get
{
return _items;
}
}
}
#endregion
}
static class PropertyExtensions
{
public static object GetProperty(this object _this, string propertyName)
{
return _this.GetType().GetTypeInfo().GetDeclaredProperty(propertyName)?.GetValue(_this);
}
}
}

Просмотреть файл

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\xunit.runner.visualstudio.2.2.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\..\packages\xunit.runner.visualstudio.2.2.0\build\net20\xunit.runner.visualstudio.props')" />
<Import Project="..\..\packages\xunit.runner.msbuild.2.2.0\build\net452\xunit.runner.msbuild.props" Condition="Exists('..\..\packages\xunit.runner.msbuild.2.2.0\build\net452\xunit.runner.msbuild.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),Microsoft.AspNet.CorrelationActivity.sln))\tools\Microsoft.AspNet.CorrelationActivity.settings.targets" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9FAE5C43-F56C-4D87-A23C-6D2D57B4ABED}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.AspNet.CorrelationActivity.Tests</RootNamespace>
<AssemblyName>Microsoft.AspNet.CorrelationActivity.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<DelaySign>true</DelaySign>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Diagnostics.DiagnosticSource.4.4.0-beta-25114-01\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Core, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.Core.3.1.1\lib\net46\System.Reactive.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Reactive.Interfaces.3.1.1\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\..\packages\xunit.assert.2.2.0\lib\netstandard1.1\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\..\packages\xunit.extensibility.core.2.2.0\lib\netstandard1.1\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.2.0.3545, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\..\packages\xunit.extensibility.execution.2.2.0\lib\net452\xunit.execution.desktop.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ActivityExtensionsTest.cs" />
<Compile Include="ActivityHelperTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNet.CorrelationActivity\Microsoft.AspNet.CorrelationActivity.csproj">
<Project>{4c8e592c-c532-4cf2-80ef-3bdd0d788d12}</Project>
<Name>Microsoft.AspNet.CorrelationActivity</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="35MSSharedLib1024.snk" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\xunit.runner.msbuild.2.2.0\build\net452\xunit.runner.msbuild.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.runner.msbuild.2.2.0\build\net452\xunit.runner.msbuild.props'))" />
<Error Condition="!Exists('..\..\packages\xunit.runner.visualstudio.2.2.0\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.runner.visualstudio.2.2.0\build\net20\xunit.runner.visualstudio.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<UsingTask AssemblyFile="$(OutputPath)xunit.runner.msbuild.dll" TaskName="Xunit.Runner.MSBuild.xunit" />
<Target Name="AfterBuild">
<xunit Assemblies="$(OutputPath)Microsoft.AspNet.CorrelationActivity.Tests.dll" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,34 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Microsoft.AspNet.CorrelationIdTracker.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Microsoft.AspNet.CorrelationIdTracker.Test")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9fae5c43-f56c-4d87-a23c-6d2d57b4abed")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]

Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Diagnostics.DiagnosticSource" version="4.4.0-beta-25114-01" targetFramework="net46" />
<package id="System.Reactive.Core" version="3.1.1" targetFramework="net46" />
<package id="System.Reactive.Interfaces" version="3.1.1" targetFramework="net46" />
<package id="xunit" version="2.2.0" targetFramework="net46" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="net46" />
<package id="xunit.assert" version="2.2.0" targetFramework="net46" />
<package id="xunit.core" version="2.2.0" targetFramework="net46" />
<package id="xunit.extensibility.core" version="2.2.0" targetFramework="net46" />
<package id="xunit.extensibility.execution" version="2.2.0" targetFramework="net46" />
<package id="xunit.runner.msbuild" version="2.2.0" targetFramework="net46" developmentDependency="true" />
<package id="xunit.runner.visualstudio" version="2.2.0" targetFramework="net46" developmentDependency="true" />
</packages>

Просмотреть файл

@ -0,0 +1,18 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Update NuGet Package version for nightly build-->
<PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.nuproj'">
<NuGetPackageVersion Condition="'$(UpdateNightlyPackages)' == 'true'">$(NuGetPackageVersion)-b$(VersionBuild)</NuGetPackageVersion>
</PropertyGroup>
<ItemGroup>
<NuGetInstallScripts Include="$(RepositoryRootEx)src\Packages\Microsoft.AspNet.CorrelationActivity\tools\*.ps1"/>
</ItemGroup>
<Target Name="CopyInstallScripts">
<Copy SourceFiles="@(NuGetInstallScripts)"
DestinationFolder="$(AssemblyPath)"
/>
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,46 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Configurable properties-->
<PropertyGroup>
<BuildQuality Condition="'$(BuildQuality)' == ''">rtm</BuildQuality>
<VersionStartYear>2017</VersionStartYear>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<VersionRelease>0</VersionRelease>
<VersionRelease Condition="'$(BuildQuality)' != 'rtm'">$(VersionRelease)-$(BuildQuality)</VersionRelease>
</PropertyGroup>
<PropertyGroup Label="NuGet package dependencies">
<DiagnosticSourceNuGetPackageVersion>4.4.0-beta-25114-01</DiagnosticSourceNuGetPackageVersion>
</PropertyGroup>
<!-- Default properties -->
<PropertyGroup>
<RepositoryRoot Condition="'$(RepositoryRoot)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Microsoft.AspNet.CorrelationActivity.sln))\</RepositoryRoot>
</PropertyGroup>
<PropertyGroup Label="Common Configuration">
<Configuration Condition="'$(Configuration)' == ''">Release</Configuration>
<OutputPath>$(RepositoryRoot)bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>$(RepositoryRoot)obj\$(Configuration)\$(MSBuildProjectName)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup>
<AssemblyPath Condition="'$(AssemblyPath)' == ''">$(OutputPath)</AssemblyPath>
<NuGetOutputPath>$(AssemblyPath)Packages</NuGetOutputPath>
<NuGetSymbolsOutputPath>$(AssemblyPath)\SymbolPackages</NuGetSymbolsOutputPath>
<TestOutputPath>$(OutputPath)test\</TestOutputPath>
</PropertyGroup>
<PropertyGroup>
<ReferencePackagesPath>$(RepositoryRoot)packages\</ReferencePackagesPath>
<NuGetPackSymbols Condition="'$(NuGetPackSymbols)' == ''">true</NuGetPackSymbols>
<SourceRootFullPath>$(RepositoryRoot)\src\$(MSBuildProjectName)\</SourceRootFullPath>
</PropertyGroup>
<PropertyGroup>
<CustomAfterMicrosoftCommonTargets>$(RepositoryRoot)tools\Microsoft.AspNet.CorrelationActivity.targets</CustomAfterMicrosoftCommonTargets>
<CustomAfterNuGetProjTargets>$(CustomAfterMicrosoftCommonTargets)</CustomAfterNuGetProjTargets>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,29 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Build order -->
<PropertyGroup>
<BuildDependsOn>SetNuSpecProperties;$(BuildDependsOn)</BuildDependsOn>
</PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)version.targets"/>
<!-- Post-targets computed properties. -->
<PropertyGroup>
<SatelliteContractVersion Condition="'$(SatelliteContractVersion)' == ''">$(AssemblyVersion)</SatelliteContractVersion>
</PropertyGroup>
<Import Project="$(CustomAfterProjectTargets)" Condition="Exists('$(CustomAfterProjectTargets)')" Label="Post-targets Build Extensibility Point" />
<!-- Target definitions -->
<Target Name="SetNuSpecProperties">
<PropertyGroup>
<NuSpecProperties>
NuGetPackageVersion=$(NuGetPackageVersion);
NuGetPackageId=$(NuGetPackageId);
DiagnosticSourceNuGetPackageVersion=$(DiagnosticSourceNuGetPackageVersion)
</NuSpecProperties>
</PropertyGroup>
</Target>
</Project>

144
tools/NuGet.targets Normal file
Просмотреть файл

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
<!-- Property that enables building a package from a project -->
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
<!-- Download NuGet.exe if it does not already exist -->
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://www.nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
</PropertyGroup>
<PropertyGroup>
<PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>
<PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
</PropertyGroup>
<PropertyGroup>
<PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
<PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet command -->
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
RestorePackages;
$(BuildDependsOn);
</BuildDependsOn>
<!-- Make the build depend on restore packages -->
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
$(BuildDependsOn);
BuildPackage;
</BuildDependsOn>
</PropertyGroup>
<Target Name="CheckPrerequisites">
<!-- Raise an error if we're unable to locate nuget.exe -->
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
<!--
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
This effectively acts as a lock that makes sure that the download operation will only happen once and all
parallel builds will have to wait for it to complete.
-->
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
</Target>
<Target Name="_DownloadNuGet">
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)"
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(BuildCommand)"
Condition=" '$(OS)' != 'Windows_NT' " />
<Exec Command="$(BuildCommand)"
LogStandardErrorAsError="true"
Condition=" '$(OS)' == 'Windows_NT' " />
</Target>
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<OutputFilename ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Net" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
OutputFilename = Path.GetFullPath(OutputFilename);
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>

500
tools/NuGetProj.targets Normal file
Просмотреть файл

@ -0,0 +1,500 @@
<!--
****************************************************************************************************
Project global nuget targets.
Relevant parameters:
* NuSpecFile property:
The name of the project's nuspec file, relative to the project or with full path.
* NuSpecCreateOnMissing property:
When true and the NuSpecFile does not exists, one can be created from params defined by the project.
* NuGetContent, NuSpecMetadata, NuSpecDependency and NuSpecFrameworkAssembly item groups:
Represent the nuspec schema. See item definitions.
* NuGetContentProject: Item containing the project path and used to add Compile (source) items into
the NuGetContent collection for symbol packages.
* SourceRootFullPath: Default value for the NuGetFromProject corresponding item metadata.
* NuSpec[metadataName] property: Following this property name pattern NuSpec metadata items can be
defined in the project, a nuspec file could be fully generated this way.
* NuSpecProperties property:
NuGet supports property replacement in the nuspec file using the '$value$' token notation.
* Note: If NuSpecFile is provided and the project defines some nuspec parameters, values from both are
merged, with precedense taken by the provided parameters. This allows for parameterization of the file.
* NuGetPackOptions property:
Represents the options passed to the NuGet.exe tool in the command line.
* NuGetPackSymbols property:
Determines whether symbols package is built. Ignored if NuGetPackOptions is defined.
* NuGetOutputPath property:
Represents the directory where the package is to be created.
* NuSpecSchemaVersion: represents the nuspec file xml schema version.
****************************************************************************************************-->
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(CustomBeforeNuGetProjTargets)" Condition="Exists('$(CustomBeforeNuGetProjTargets)')"/>
<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<OutputPath Condition="'$(OutputPath)' == ''">bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath Condition="'$(IntermediateOutputPath)' == ''">obj\$(Configuration)\</IntermediateOutputPath>
<IntermediateOutputPath Condition="'$(NuGetPackageLanguage)' != ''">$(IntermediateOutputPath)$(NuGetPackageLanguage)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup>
<!-- The NuGet package name inlcudes the nusepc id and version which are ultimately taken from the NuSpec file. -->
<!-- The nuspec metadata is usually specified in the nuspec file (if provided). When NuSpec<metaName> props are specified they overwrite the nuspec items. -->
<!-- NuGetPackageID and NuSpecID should have the same value, the former is kept for legacy reasons (same for version properties). -->
<NuSpecId Condition="'$(NuSpecId)' == ''">$(MSBuildProjectName)</NuSpecId>
<NuGetPackageId Condition="'$(NuGetPackageId)' == ''">$(NuSpecId)</NuGetPackageId>
<NuGetPackageVersion Condition="'$(NuGetPackageVersion)' == ''">$(NuSpecVersion)</NuGetPackageVersion>
<NuSpecVersion Condition="'$(NuSpecVersion)' == ''">$(NuGetPackageVersion)</NuSpecVersion>
</PropertyGroup>
<PropertyGroup>
<NuSpecSchemaVersion Condition="'$(NuSpecSchemaVersion)' == ''">2</NuSpecSchemaVersion>
<NuGetPackSymbols Condition="'$(NuGetPackOptions.ToLower().Contains(symbols))'">true</NuGetPackSymbols>
<NuGetPackSymbols Condition="'$(NuGetPackSymbols)' == ''">false</NuGetPackSymbols>
<NuSpecFile Condition="'$(NuSpecFile)' == ''">$(MSBuildProjectDirectory)\$(NuGetPackageId).nuspec</NuSpecFile>
<NuSpecFileName>$([System.IO.Path]::GetFileName('$(NuSpecFile)'))</NuSpecFileName>
<NuSpecCreateOnMissing Condition="'$(NuSpecCreateOnMissing)' == ''">true</NuSpecCreateOnMissing>
<NuGetProjectOutputsFile>$(IntermediateOutputPath)$(NuGetPackageId).outputs</NuGetProjectOutputsFile>
</PropertyGroup>
<PropertyGroup Label="NuGet.targets inputs">
<NuGetExePath Condition="!Exists('$(NuGetExePath)')">$([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildThisFileFullPath)', '.nuget\nuget.targets'))\.nuget\NuGet.exe</NuGetExePath>
<NuGetInstallPath>$([System.IO.Path]::GetDirectoryName('$(NuGetExePath)'))</NuGetInstallPath>
<PackageOutputDir Condition="'$(NuGetOutputPath)' != ''">$(NuGetOutputPath)</PackageOutputDir>
<PackageOutputDir Condition="'$(PackageOutputDir)' == ''">$(OutputPath)NuGet</PackageOutputDir>
<PackageOutputDir>$(PackageOutputDir.TrimEnd('\'))</PackageOutputDir>
<NuGetOutputPath Condition="'$(NuGetOutputPath)' == ''">$(PackageOutputDir)</NuGetOutputPath>
<ProjectPath>$(IntermediateOutputPath)$(NuSpecFileName)</ProjectPath>
</PropertyGroup>
<PropertyGroup>
<CodeTaskFactoryAssemblyFile Condition=" '$(CodeTaskFactoryAssemblyFile)' == '' And '$(MSBuildToolsVersion)' == '12.0' ">$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll</CodeTaskFactoryAssemblyFile>
<CodeTaskFactoryAssemblyFile Condition=" '$(CodeTaskFactoryAssemblyFile)' == '' ">$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll</CodeTaskFactoryAssemblyFile>
</PropertyGroup>
<PropertyGroup>
<!--Force a rebuild if this file is changed -->
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath);$(MSBuildProjectFullPath)</MSBuildAllProjects>
</PropertyGroup>
<!--
NuGet package layout conventions http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package#Package_Conventions
NuSpec metadata schema https://nuget.codeplex.com/wikipage?title=.nuspec%20v1.2%20Format
-->
<ItemDefinitionGroup>
<!-- NuGetContent represents the files to be packed (dll, exe, pdb, .cs, content, etc). -->
<NuGetContent>
<Source>$(NuGetContentSource)</Source>
<Destination>$(NuGetContentDestination)</Destination>
</NuGetContent>
<!-- NuSpecMetadata represents the simple items under the 'metadata' schema element (title, version, etc.) -->
<NuSpecMetadata>
<Value/>
</NuSpecMetadata>
<!-- NuSpecDependency represents the child element of the complex 'metadata/dependencies' schema element. -->
<NuSpecDependency>
<Version/>
<TargetFramework/>
</NuSpecDependency>
<!-- NuSpecFrameworkAssembly represents the child element of the complex 'metadata/frameworkAssemblies' schema element. -->
<NuSpecFrameworkAssembly>
<TargetFramework/>
</NuSpecFrameworkAssembly>
</ItemDefinitionGroup>
<!--
NuGetContentFromProject: Defines content from the Compile item collection (source files) from projects into the NuGetContent item.
-->
<ItemDefinitionGroup>
<NuGetContentProject>
<SourceRootFullPath>$(SourceRootFullPath)</SourceRootFullPath>
<Destination>src</Destination>
</NuGetContentProject>
</ItemDefinitionGroup>
<ItemGroup>
<!-- NuSpec file added by default. -->
<NuGetContent Include="$(ProjectPath)" />
</ItemGroup>
<!-- Optional NuSpec file metadata items. When provided, items are used for generating the final nuspec file. -->
<!-- http://docs.nuget.org/docs/reference/nuspec-reference -->
<ItemGroup>
<NuSpecMetadata Include="id" Condition="'$(NuSpecId)' != ''">
<Value>$(NuSpecId)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="version" Condition="'$(NuSpecVersion)' != ''">
<Value>$(NuSpecVersion)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="title" Condition="'$(NuSpecTitle)' != ''">
<Value>$(NuSpecTitle)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="authors" Condition="'$(NuSpecAuthors)' != ''">
<Value>$(NuSpecAuthors)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="owners" Condition="'$(NuSpecOwners)' != ''">
<Value>$(NuSpecOwners)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="description" Condition="'$(NuSpecDescription)' != ''">
<Value>$(NuSpecDescription)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="tags" Condition="'$(NuSpecTags)' != ''">
<Value>$(NuSpecTags)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="iconUrl" Condition="'$(NuSpecIconUrl)' != ''">
<Value>$(NuSpecIconUrl)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="projectUrl" Condition="'$(NuSpecProjectUrl)' != ''">
<Value>$(NuSpecProjectUrl)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="licenseUrl" Condition="'$(NuSpecLicenseUrl)' != ''">
<Value>$(NuSpecLicenseUrl)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="copyright" Condition="'$(NuSpecCopyright)' != ''">
<Value>$(NuSpecCopyright)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="requireLicenseAcceptance" Condition="'$(NuSpecRequireLicenseAcceptance)' != ''">
<Value>$(NuSpecRequireLicenseAcceptance)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="releaseNotes" Condition="'$(NuSpecReleaseNotes)' != ''">
<Value>$(NuSpecReleaseNotes)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="summary" Condition="'$(NuSpecSummary)' != ''">
<Value>$(NuSpecSummary)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="developmentDependency" Condition="'$(NuSpecDevelopmentDependency)' != ''">
<Value>$(NuSpecDevelopmentDependency)</Value>
</NuSpecMetadata>
<NuSpecMetadata Include="language" Condition="'$(NuSpecLanguage)' != ''">
<Value>$(NuSpecLanguage)</Value>
</NuSpecMetadata>
</ItemGroup>
<ItemGroup>
<Clean Include="$(NuGetProjectOutputsFile)" />
</ItemGroup>
<!--
****************************************************************************************************
Common build targets overwrites.
**************************************************************************************************** -->
<PropertyGroup>
<BuildDependsOn>BeforeBuild;GetNuGetContentFromProject;ValidateNuGetParams;ReadNuGetCleanOutputs;GetNuGetProjectInputs;GetNuGetProjectOutputs;ValidateOutputs;NuGetPack;WriteNuGetProjectOutputs;AfterBuild</BuildDependsOn>
<CleanDependsOn>BeforeClean;ReadNuGetCleanOutputs;CoreClean;AfterClean</CleanDependsOn>
<RebuildDependsOn>Clean;Build</RebuildDependsOn>
</PropertyGroup>
<Target Name="BeforeBuild" />
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)" />
<Target Name="AfterBuild" />
<Target Name="BeforeClean" />
<Target Name="Clean" DependsOnTargets="$(CleanDependsOn)"/>
<Target Name="AfterClean" />
<Target Name="CoreClean">
<Delete Files="@(Clean)" />
<ItemGroup>
<Clean Remove="@(Clean)" />
</ItemGroup>
</Target>
<Target Name="Rebuild" DependsOnTargets="$(RebuildDependsOn)" />
<!--
****************************************************************************************************
GetNuGetContentFromProject: Gets Compile item collection (source files) from projects into the NuGetContent item.
Input: NuGetContentProject and SourceRootFullPath
**************************************************************************************************** -->
<Target Name="GetNuGetContentFromProject" Condition="'@(NuGetContentProject)' != ''">
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="GetNuGetContentFromProjectCore"
Properties="NuGetContentProject=%(NuGetContentProject.FullPath);SourceRootFullPath=%(SourceRootFullPath);Destination=%(Destination)" >
<Output TaskParameter="TargetOutputs" ItemName="NuGetContent" />
</MSBuild>
</Target>
<Target Name="GetNuGetContentFromProjectCore" Outputs="@(NuGetContent)">
<Error Condition="'$(SourceRootFullPath)' == ''" Text="NuGetContentProject item does not define 'SourceRootFullPath' metadata: $(NuGetContentProject)" />
<PropertyGroup>
<!-- Normalize path (remove extra back-slashes and trim) -->
<SourceRootFullPath>$([System.IO.Path]::GetFullPath($(SourceRootFullPath)))</SourceRootFullPath>
</PropertyGroup>
<MSBuild Projects="$(NuGetContentProject)" Targets="GetCompile" RebaseOutputs="true">
<Output TaskParameter="TargetOutputs" ItemName="Compile" />
</MSBuild>
<ItemGroup>
<NugetContent Include="%(Compile.FullPath)" Condition="$([System.String]::Concat(%(FullPath)).ToLower().Contains($(SourceRootFullPath.ToLower())))">
<Destination>$([System.IO.Path]::Combine($(Destination), $([MSBuild]::MakeRelative($([System.IO.Path]::GetFullPath($(SourceRootFullPath))), %(Compile.RootDir)%(Directory)))))</Destination>
</NugetContent>
</ItemGroup>
</Target>
<!--
****************************************************************************************************
ValidateNuGetParams: validate input params.
****************************************************************************************************-->
<Target Name="ValidateNuGetParams">
<ItemGroup>
<PropMismatch Include="NuSpecID=$(NuSpecID) and NuGetPackageID=$(NuGetPackageID)"
Condition="'$(NuSpecId)' != '' AND '$(NuGetPackageID)' != '' AND '$(NuSpecId)' != '$(NuGetPackageID)'" />
<PropMismatch Include="NuSpecVersion=$(NuSpecVersion) and NuGetPackageVersion=$(NuGetPackageVersion)"
Condition="'$(NuSpecVersion)' != '' AND '$(NuGetPackageVersion)' != '' AND '$(NuSpecVersion)' != '$(NuGetPackageVersion)'" />
</ItemGroup>
<Warning Text="No content was specified " Condition="'@(NuGetContent)' == '' AND '$(DisableNoNuGetContentWarning)' != 'true'" />
<Error Text="@(PropMismatch -> '%(Identity) are different, this is an indication of an authoring error!', '%0A')" Condition="'@(PropMismatch)' != ''" />
<Error Text="Could not find nuspec file: $(NuSpecFile)" Condition="!Exists('$(NuSpecFile)') AND '$(NuSpecCreateOnMissing)' == 'false'" />
</Target>
<!--
****************************************************************************************************
ValidateOutputs: checks whether outputs are up-to-date with respect to the inputs to avoid rebuilding
if not needed and play nicely when building incrementally.
**************************************************************************************************** -->
<Target Name="ValidateOutputs" Inputs="@(NuGetProjectInput);$(MSBuildAllProjects)" Outputs="@(NuGetProjectOutput)">
<CreateProperty Value="true">
<Output TaskParameter="ValueSetByTask" PropertyName="OutputsOutdated"/>
</CreateProperty>
</Target>
<!--
****************************************************************************************************
NuGetPack: Creates a nuget package.
**************************************************************************************************** -->
<Target Name="NuGetPack" DependsOnTargets="GenerateNuSpecFile" Condition="'$(OutputsOutdated)' == 'true'">
<ItemGroup>
<!-- Normalize comman-separated property string (removes new lines and trims string)-->
<NuSpecProperties Include="$(NuSpecProperties)" />
</ItemGroup>
<PropertyGroup>
<NuSpecProperties>@(NuSpecProperties)</NuSpecProperties>
<NuGetPackOptions Condition="'$(NuGetPackOptions)' == '' AND '$(NuGetPackSymbols)' != 'true'">-NoPackageAnalysis</NuGetPackOptions>
<NuGetPackOptions Condition="'$(NuGetPackOptions)' == '' AND '$(NuGetPackSymbols)' == 'true'">-NoPackageAnalysis -symbols</NuGetPackOptions>
<!-- BuildCommand is defined in nuget.targets file -->
<BuildCommand>$(BuildCommand.Replace('-symbols', ''))</BuildCommand>
<BuildCommand>$(BuildCommand.Replace('/symbols', ''))</BuildCommand>
<BuildCommand Condition="'$(NuSpecProperties)' != ''">$(BuildCommand) -Properties "$(NuSpecProperties)"</BuildCommand>
<BuildCommand Condition="'$(NuGetPackOptions)' != ''">$(BuildCommand) $(NuGetPackOptions)</BuildCommand>
</PropertyGroup>
<!-- Invalidate outputs to force a full build in case of failure -->
<Delete Files="$(NuGetPackTargetFile)" />
<MakeDir Directories="$(PackageOutputDir)" />
<Exec Command="$(BuildCommand)" StandardOutputImportance="high" StandardErrorImportance="high" WorkingDirectory="$(MSBuildProjectDirectory)" CustomErrorRegularExpression="invalid"/>
<ItemGroup>
<Clean Include="$(PackageOutputDir)\$(NuGetPackageId).$(NuGetPackageVersion)*.nupkg" />
</ItemGroup>
<!-- This target can fail preventing outputs file from being updated, neet to account for that. -->
<OnError ExecuteTargets="WriteNuGetProjectOutputs" />
</Target>
<!--
****************************************************************************************************
GetNuGetProjectInputs: get the project inputs.
**************************************************************************************************** -->
<Target Name="GetNuGetProjectInputs">
<NormalizeNuGetContent NuGetContent="@(NuGetContent)">
<Output TaskParameter="NuGetContentNormalized" ItemName="NuGetProjectInput" />
</NormalizeNuGetContent>
</Target>
<!--
****************************************************************************************************
GetNuGetProjectOutputs: Reads build-generated files from outputs file.
**************************************************************************************************** -->
<Target Name="GetNuGetProjectOutputs">
<PropertyGroup>
<NuGetPackTargetFile>$(PackageOutputDir)\$(NuGetPackageId).$(NuGetPackageVersion).nupkg</NuGetPackTargetFile>
<NuGetPackTargetFile Condition="'$(NuGetPackSymbols)' == 'true'">$(PackageOutputDir)\$(NuGetPackageId).$(NuGetPackageVersion).symbols.nupkg</NuGetPackTargetFile>
</PropertyGroup>
<ItemGroup>
<NuGetProjectOutput Include="$(NuGetPackTargetFile)" />
<NuGetProjectOutput Include="$(NuGetProjectOutputsFile)" />
</ItemGroup>
</Target>
<!--
****************************************************************************************************
ReadNuGetCleanOutputs: Reads build-generated files from outputs file into Clean item collection to
get them re-written into outputs file so they can be cleaned up later.
**************************************************************************************************** -->
<Target Name="ReadNuGetCleanOutputs">
<ReadLinesFromFile File="$(NuGetProjectOutputsFile)">
<Output TaskParameter="Lines" ItemName="Clean" />
</ReadLinesFromFile>
</Target>
<!--
****************************************************************************************************
WriteNuGetProjectOutputs: write the list of build-generated files into outputs file which is used for
cleaning and incremental build.
**************************************************************************************************** -->
<Target Name="WriteNuGetProjectOutputs" Condition="'$(OutputsOutdated)' == 'true'">
<ItemGroup>
<NuGetProjectOutput Include="@(Clean->Distinct())" />
</ItemGroup>
<WriteLinesToFile File="$(NuGetProjectOutputsFile)" Lines="@(NuGetProjectOutput->Distinct())" Overwrite="true" Condition="'@(NuGetProjectOutput)' != ''" />
</Target>
<!--
****************************************************************************************************
GenerateNuSpecFile: generates the final nuspec file for the package.
**************************************************************************************************** -->
<Target Name="GenerateNuSpecFile" DependsOnTargets="GetNuGetProjectInputs" Condition="'$(OutputsOutdated)' == 'true'">
<GenerateNuSpecFile NuSpecFile="$(NuSpecFile)" OutputDir="$(IntermediateOutputPath)" CreateNuSpec="$(NuSpecCreateOnMissing)" MetadataItems="@(NuSpecMetadata)"
Files="@(NuGetProjectInput);@(NuGetContentFromPdb)" FrameworkAssemblies="@(NuSpecFrameworkAssembly)" Dependencies="@(NuSpecDependency)" SchemaVersion="$(NuSpecSchemaVersion)">
<Output TaskParameter="GeneratedNuSpec" PropertyName="GeneratedNuSpec" />
</GenerateNuSpecFile>
<ItemGroup>
<Clean Include="$(GeneratedNuSpec)" />
</ItemGroup>
<Message Text="Generated NuSpec file: $(GeneratedNuSpec)" />
</Target>
<!--
==================================================================================================
Generates final nuspec file combining/replacing values from project nuspec file if provided.
==================================================================================================-->
<UsingTask TaskName="GenerateNuSpecFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(CodeTaskFactoryAssemblyFile)">
<ParameterGroup>
<NuSpecFile Required="true" ParameterType="System.String" />
<MetadataItems Required="false" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<Files Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<FrameworkAssemblies Required="false" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<Dependencies Required="false" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<OutputDir Required="true" ParameterType="System.String" />
<CreateNuSpec Required="false" ParameterType="System.Boolean" />
<SchemaVersion Required="true" ParameterType="System.Int32" />
<GeneratedNuSpec Output="true" ParameterType="System.String" />
</ParameterGroup>
<Task>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Using Namespace="System.Linq" />
<Using Namespace="System.IO" />
<Using Namespace="System.Xml.Linq" />
<Code Type="Fragment" Language="cs">
<![CDATA[
XElement packageNode = null;
if (File.Exists(NuSpecFile)) {
packageNode = XElement.Load(NuSpecFile);
} else {
if (!CreateNuSpec) { Log.LogError("NuSpec file does not exist: {0}", NuSpecFile); return false; }
if(SchemaVersion > 1) {
XNamespace pkgNs = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd";
packageNode = new XElement(pkgNs + "package", new XElement("metadata", new XAttribute("schemaVersion", SchemaVersion)));
} else {
packageNode = new XElement("package", new XElement("metadata"));
}
}
GeneratedNuSpec = Path.GetFullPath(Path.Combine(OutputDir, Path.GetFileName(NuSpecFile)));
if (File.Exists(GeneratedNuSpec)) File.Delete(GeneratedNuSpec);
XNamespace ns = packageNode.Name.Namespace;
if(packageNode.Name.LocalName != "package") { Log.LogError("NuSpec file missing 'package' schema element. Found:'{0}'", packageNode.Name.LocalName); return false; };
if (Files == null) Files = new TaskItem[] { };
if (Dependencies == null) Dependencies = new TaskItem[] { };
if (MetadataItems == null) MetadataItems = new TaskItem[] { };
if (FrameworkAssemblies == null) FrameworkAssemblies = new TaskItem[] { };
// replace/add simple metadata.
XElement metadataNode = packageNode.FirstNode as XElement;
if(metadataNode == null) { Log.LogError("NuSpec file missing 'metadata' schema element"); return false; };
foreach (var metaItem in MetadataItems) {
string name = metaItem.GetMetadata("Identity");
string value = metaItem.GetMetadata("Value");
XElement xnode = metadataNode.Descendants(ns + name).FirstOrDefault<XElement>();
if (xnode == null) { xnode = new XElement(name); metadataNode.Add(xnode); }
xnode.Value = value;
}
// replaceable values for dependencies and frameworkassemblies - just replace the whole node.
var removeQ1 = from dependencyNode in packageNode.Descendants(ns + "dependency").Attributes("id")
from dependencyItem in Dependencies
where dependencyItem.GetMetadata("Identity").ToLower().Equals(dependencyNode.Value.ToLower())
select dependencyNode.Parent;
var removeQ2 = from assemblyNode in packageNode.Descendants(ns + "frameworkAssembly").Attributes("assemblyName")
from assemblyItem in FrameworkAssemblies
where assemblyItem.GetMetadata("Identity").ToLower().Equals(assemblyNode.Value.ToLower())
select assemblyNode.Parent;
foreach (var node in removeQ1.ToArray<XElement>()) node.Remove();
foreach (var node in removeQ2.ToArray<XElement>()) node.Remove();
XElement filesNode = packageNode.Descendants(ns + "files").FirstOrDefault<XElement>();
if (filesNode == null) {
filesNode = new XElement("files");
packageNode.Add(filesNode);
}
filesNode.Add(from fi in Files select new XElement("file", new XAttribute("src", fi.GetMetadata("FullPath")), new XAttribute("target", fi.GetMetadata("Destination"))));
XElement frameworkAssembliesNode = packageNode.Descendants(ns + "frameworkAssemblies").FirstOrDefault<XElement>();
if (frameworkAssembliesNode == null) {
frameworkAssembliesNode = new XElement("frameworkAssemblies");
metadataNode.Add(frameworkAssembliesNode);
}
frameworkAssembliesNode.Add(from assembly in FrameworkAssemblies select new XElement("frameworkAssembly",
new XAttribute("assemblyName", assembly.GetMetadata("Identity")), new XAttribute("targetFramework", assembly.GetMetadata("TargetFramework"))));
XElement dependenciesNode = packageNode.Descendants(ns + "dependencies").FirstOrDefault<XElement>();
if (dependenciesNode == null) {
dependenciesNode = new XElement("dependencies");
metadataNode.Add(dependenciesNode);
}
if(SchemaVersion > 1) {
var depGroupsQ = from dp in Dependencies group dp by dp.GetMetadata("TargetFramework");
foreach (var dpGroup in depGroupsQ) {
XElement depGroupNode = new XElement("group");
string targetFx = dpGroup.First().GetMetadata("TargetFramework");
if(!string.IsNullOrEmpty(targetFx)) depGroupNode.Add(new XAttribute("targetFramework", dpGroup.First().GetMetadata("TargetFramework")));
foreach(var depItem in dpGroup) {
XElement dependencyNode = new XElement("dependency", new XAttribute("id", depItem.GetMetadata("Identity")), new XAttribute("version", depItem.GetMetadata("Version")));
depGroupNode.Add(dependencyNode);
}
dependenciesNode.Add(depGroupNode);
}
} else {
dependenciesNode.Add(from dp in Dependencies select new XElement("dependency", new XAttribute("id", dp.GetMetadata("Identity")), new XAttribute("version", dp.GetMetadata("Version"))));
}
if (!Directory.Exists(OutputDir)) Directory.CreateDirectory(OutputDir);
packageNode.Save(GeneratedNuSpec);
]]>
</Code>
</Task>
</UsingTask>
<!--
****************************************************************************************************
NormalizeNuGetContent: Normalize NuGetContent items full path and destination for packing.
****************************************************************************************************-->
<UsingTask TaskName="NormalizeNuGetContent" TaskFactory="CodeTaskFactory" AssemblyFile="$(CodeTaskFactoryAssemblyFile)">
<ParameterGroup>
<NuGetContent Required="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
<NuGetContentNormalized Output="true" ParameterType="Microsoft.Build.Framework.ITaskItem[]" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO" />
<Code Type="Fragment" Language="cs">
<![CDATA[
NuGetContentNormalized = new TaskItem[NuGetContent.Length];
for (int idx = 0; idx < NuGetContent.Length; idx++) {
string src = NuGetContent[idx].GetMetadata("Source");
string id = NuGetContent[idx].GetMetadata("Identity");
if (!string.IsNullOrEmpty(src) && !Path.IsPathRooted(id)) {
NuGetContentNormalized[idx] = new TaskItem(Path.Combine(src, id));
}
else {
NuGetContentNormalized[idx] = new TaskItem(NuGetContent[idx].GetMetadata("FullPath"));
}
NuGetContentNormalized[idx].SetMetadata("Destination", NuGetContent[idx].GetMetadata("Destination"));
}
]]>
</Code>
</Task>
</UsingTask>
<Import Project="$(NuGetInstallPath)\nuget.targets" />
<Import Project="$(CustomAfterNuGetProjTargets)" Condition="Exists('$(CustomAfterNuGetProjTargets)')"/>
</Project>

112
tools/version.targets Normal file
Просмотреть файл

@ -0,0 +1,112 @@
<!--
****************************************************************************************************
Project global versioning targets.
****************************************************************************************************-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Input parameters -->
<!-- NOTE: The VersionFileAttribute ItemGroup can be used to add assembly-level attributes to the generated version file, ex:
<VersionFileAttribute Include="[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(&quot;Microsoft.Usage&quot;, &quot;CA2243:AttributeStringLiteralsShouldParseCorrectly&quot;, Justification = &quot;Justification here&quot;)]" />
-->
<PropertyGroup>
<VersionFileGenerationEnabled Condition="'$(VersionFileGenerationEnabled)' == '' AND '$(MSBuildProjectExtension)' == '.csproj'">true</VersionFileGenerationEnabled>
<VersionFileGenerationEnabled Condition="'$(VersionFileGenerationEnabled)' == ''">false</VersionFileGenerationEnabled>
</PropertyGroup>
<PropertyGroup>
<VersionStartYear Condition="'$(VersionStartYear)' == ''">2013</VersionStartYear>
<VersionMajor Condition="'$(VersionMajor)' == ''">INVALID_VersionMajor</VersionMajor>
<VersionMinor Condition="'$(VersionMinor)' == ''">INVALID_VersionMinor</VersionMinor>
<VersionBuild Condition="'$(VersionBuild)' == '' OR '$(VersionBuild)' == '0'">$([MSBuild]::Add(1, $([MSBuild]::Subtract($([System.DateTime]::Now.Year), $(VersionStartYear)))))$([System.DateTime]::Now.ToString("MMdd"))</VersionBuild>
<VersionRevision Condition="'$(VersionRevision)' == ''">0</VersionRevision>
<VersionRelease Condition="'$(VersionRelease)' == ''">0</VersionRelease>
</PropertyGroup>
<!-- Comptued parameters -->
<PropertyGroup>
<AssemblyVersion>$(VersionMajor).$(VersionMinor).$(VersionRelease).$(VersionRevision)</AssemblyVersion>
<AssemblyFileVersion>$(VersionMajor).$(VersionMinor).$(VersionBuild).$(VersionRevision)</AssemblyFileVersion>
<AssemblyInfoVersion Condition="'$(VersionRelease)' != ''">$(VersionMajor).$(VersionMinor).$(VersionRelease)-$(VersionBuild)</AssemblyInfoVersion>
<AssemblyInfoVersion Condition="'$(AssemblyInfoVersion)' == ''">$(AssemblyFileVersion)</AssemblyInfoVersion>
<AssemblyVersionFile>$(IntermediateOutputPath)$(MSBuildProjectName).version.cs</AssemblyVersionFile>
</PropertyGroup>
<PropertyGroup>
<NuGetPackageVersion Condition="'$(NuGetPackageVersion)' == ''">$(VersionMajor).$(VersionMinor).$(VersionRelease)-beta-$(VersionBuild)-01</NuGetPackageVersion>
</PropertyGroup>
<ItemGroup Condition="'$(VersionFileGenerationEnabled)' == 'true'">
<Compile Include="$(AssemblyVersionFile)" />
</ItemGroup>
<ItemGroup>
<Clean Include="$(AssemblyVersionFile)" Condition="'$(MSBuildProjectExtension)' == '.csproj'"/>
</ItemGroup>
<PropertyGroup Condition="'$(VersionFileGenerationEnabled)' == 'true'">
<!-- Disable assembly version defined in CommonAssemblyInfo.cs file -->
<DefineConstants>$(DefineConstants);BUILD_GENERATED_VERSION</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<!--Force a rebuild if this file is changed -->
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<!--
==================================================================================================
GenerateVersionFile target: generates assembly attributes into a source file that is included
in the items to compile.
================================================================================================== -->
<PropertyGroup Condition="'$(VersionFileGenerationEnabled)' == 'true'">
<CompileDependsOn>GenerateVersionFile;$(CompileDependsOn)</CompileDependsOn>
<GenerateVersionFileDependsOn>ValidateVersionValues;ShouldGenerateVersionFile;GenerateVersionFileCore</GenerateVersionFileDependsOn>
</PropertyGroup>
<Target Name="GenerateVersionFile" DependsOnTargets="$(GenerateVersionFileDependsOn)" />
<Target Name="GenerateVersionFileCore" Condition="'$(ShouldGenerateVersionFile)' == 'true'">
<ItemGroup>
<LinesToWrite Include="// $(SourceFileCopyright)" Condition="'$(SourceFileCopyright)' != ''"/>
<LinesToWrite Include="// &lt;auto-generated&gt;" />
<LinesToWrite Include="// This code was generated by a tool." />
<LinesToWrite Include="// &lt;/auto-generated&gt;" />
<LinesToWrite Include="[assembly: System.Reflection.AssemblyCompany(&quot;$(AssemblyCompany)&quot;)]" Condition="'$(AssemblyCompany)' != ''"/>
<LinesToWrite Include="[assembly: System.Reflection.AssemblyCopyright(&quot;$(AssemblyCopyright)&quot;)]" Condition="'$(AssemblyCopyright)' != ''"/>
<LinesToWrite Include="[assembly: System.Reflection.AssemblyVersion(&quot;$(AssemblyVersion)&quot;)]" Condition="'$(AssemblyVersion)' != ''"/>
<LinesToWrite Include="[assembly: System.Reflection.AssemblyFileVersion(&quot;$(AssemblyFileVersion)&quot;)]" Condition="'$(AssemblyFileVersion)' != ''"/>
<LinesToWrite Include="[assembly: System.Reflection.AssemblyInformationalVersion(&quot;$(AssemblyInfoVersion)&quot;)]" Condition="'$(AssemblyInfoVersion)' != ''" />
<LinesToWrite Include="[assembly: System.Resources.SatelliteContractVersionAttribute(&quot;$(SatelliteContractVersion)&quot;)]" Condition="'$(SatelliteContractVersion)' != ''"/>
<LinesToWrite Include="@(VersionFileAttribute)" Condition="'@(VersionFileAttribute)' != ''" />
</ItemGroup>
<WriteLinesToFile File="$(AssemblyVersionFile)" Lines="@(LinesToWrite)" Overwrite="true" Encoding="Unicode"/>
<Message Text="Assembly Version File: $(AssemblyVersionFile)" />
</Target>
<!--
==================================================================================================
ShouldGenerateVersionFile target: determines whether a version needs to be generated.
================================================================================================== -->
<Target Name="ShouldGenerateVersionFile">
<ReadLinesFromFile File="$(AssemblyVersionFile)" Condition="Exists('$(AssemblyVersionFile)')">
<Output ItemName="VersionText" TaskParameter="Lines"/>
</ReadLinesFromFile>
<PropertyGroup>
<VersionText>@(VersionText)</VersionText>
<ShouldGenerateVersionFile>!$(VersionText.Contains('$(AssemblyFileVersion)'))</ShouldGenerateVersionFile>
</PropertyGroup>
</Target>
<Target Name="ValidateVersionValues">
<!-- Throw if any of the version values is not int16 -->
<PropertyGroup>
<VersionMajor>$([System.Convert]::ToInt16('$(VersionMajor)'))</VersionMajor>
<VersionMinor>$([System.Convert]::ToInt16('$(VersionMinor)'))</VersionMinor>
<VersionBuild>$([System.Convert]::ToInt32('$(VersionBuild)'))</VersionBuild>
<VersionRevision>$([System.Convert]::ToInt16('$(VersionRevision)'))</VersionRevision>
</PropertyGroup>
</Target>
</Project>