Integrated pull request from rposener for SQL storage provider for WebHook registrations!
This commit is contained in:
Родитель
73f0c0d60e
Коммит
7464765a61
|
@ -18,6 +18,7 @@
|
|||
<Word>salesforce</Word>
|
||||
<Word>kudu</Word>
|
||||
<Word>trello</Word>
|
||||
<Word>ver</Word>
|
||||
<Word>你好</Word>
|
||||
</Recognized>
|
||||
<Deprecated/>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<Value>\.generated\.cs$</Value>
|
||||
<Value>\.g\.i\.cs$</Value>
|
||||
<Value>TemporaryGeneratedFile_.*\.cs$</Value>
|
||||
<Value>\.Designer\.cs$</Value>
|
||||
</CollectionProperty>
|
||||
</ParserSettings>
|
||||
</Parser>
|
||||
|
|
18
WebHooks.sln
18
WebHooks.sln
|
@ -108,6 +108,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureReceivers", "samples\A
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstagramReceiver", "samples\InstagramReceiver\InstagramReceiver.csproj", "{3F9F62DD-C365-4FEC-A10E-5314D111EBF5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.WebHooks.Custom.SqlStorage", "src\Microsoft.AspNet.WebHooks.Custom.SqlStorage\Microsoft.AspNet.WebHooks.Custom.SqlStorage.csproj", "{EAC99E25-F698-41B2-8671-740D642781AB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.WebHooks.Custom.SqlStorage.Test", "test\Microsoft.AspNet.WebHooks.Custom.SqlStorage.Test\Microsoft.AspNet.WebHooks.Custom.SqlStorage.Test.csproj", "{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
|
||||
|
@ -379,6 +383,18 @@ Global
|
|||
{3F9F62DD-C365-4FEC-A10E-5314D111EBF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F9F62DD-C365-4FEC-A10E-5314D111EBF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F9F62DD-C365-4FEC-A10E-5314D111EBF5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -428,6 +444,8 @@ Global
|
|||
{D6287838-8329-4349-90F1-D9CBF49EDCEA} = {9575CB90-BC4B-43BB-8AEA-82C53FDA4187}
|
||||
{5DFA6EF9-2417-47AF-B8BB-424E420D9464} = {E957C8D9-B4A0-488B-838F-BAB4DE080A76}
|
||||
{3F9F62DD-C365-4FEC-A10E-5314D111EBF5} = {E957C8D9-B4A0-488B-838F-BAB4DE080A76}
|
||||
{EAC99E25-F698-41B2-8671-740D642781AB} = {929F44D0-A040-4DC3-A22F-4C5829C05D44}
|
||||
{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F} = {9575CB90-BC4B-43BB-8AEA-82C53FDA4187}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
|
||||
</configSections>
|
||||
<entityFramework>
|
||||
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
|
||||
<parameters>
|
||||
<parameter value="mssqllocaldb" />
|
||||
</parameters>
|
||||
</defaultConnectionFactory>
|
||||
<providers>
|
||||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
|
||||
</providers>
|
||||
</entityFramework>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Data.Entity;
|
||||
using Microsoft.AspNet.DataProtection;
|
||||
using Microsoft.AspNet.WebHooks;
|
||||
using Microsoft.AspNet.WebHooks.Config;
|
||||
using Microsoft.AspNet.WebHooks.Diagnostics;
|
||||
using Microsoft.AspNet.WebHooks.Services;
|
||||
using Microsoft.AspNet.WebHooks.Storage;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace System.Web.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="HttpConfiguration"/>.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static class HttpConfigurationExtensions
|
||||
{
|
||||
private const string ApplicationName = "Microsoft.AspNet.WebHooks";
|
||||
private const string Purpose = "WebHookPersistence";
|
||||
private const string DataProtectionKeysFolderName = "DataProtection-Keys";
|
||||
|
||||
/// <summary>
|
||||
/// Configures a Microsoft SQL Server Storage implementation of <see cref="IWebHookStore"/>
|
||||
/// which provides a persistent store for registered WebHooks used by the custom WebHooks module.
|
||||
/// </summary>
|
||||
/// <param name="config">The current <see cref="HttpConfiguration"/>config.</param>
|
||||
public static void InitializeCustomWebHooksSqlStorage(this HttpConfiguration config)
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
throw new ArgumentNullException("config");
|
||||
}
|
||||
|
||||
WebHooksConfig.Initialize(config);
|
||||
|
||||
ILogger logger = config.DependencyResolver.GetLogger();
|
||||
SettingsDictionary settings = config.DependencyResolver.GetSettings();
|
||||
|
||||
// We explicitly set the DB initializer to null to avoid that an existing DB is initialized wrongly.
|
||||
Database.SetInitializer<WebHookContext>(null);
|
||||
|
||||
IDataProtectionProvider provider = GetDataProtectionProvider();
|
||||
IDataProtector protector = provider.CreateProtector(Purpose);
|
||||
|
||||
IWebHookStore store = new SqlWebHookStore(settings, protector, logger);
|
||||
CustomServices.SetStore(store);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This follows the same initialization that is provided when <see cref="IDataProtectionProvider"/>
|
||||
/// is initialized within ASP.NET 5.0 Dependency Injection.
|
||||
/// </summary>
|
||||
/// <returns>A fully initialized <see cref="IDataProtectionProvider"/>.</returns>
|
||||
internal static IDataProtectionProvider GetDataProtectionProvider()
|
||||
{
|
||||
ServiceCollection serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddDataProtection();
|
||||
IServiceProvider services = serviceCollection.BuildServiceProvider();
|
||||
return services.GetDataProtectionProvider();
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,161 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),WebHooks.sln))\tools\WebHooks.settings.targets" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{EAC99E25-F698-41B2-8671-740D642781AB}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.AspNet.WebHooks</RootNamespace>
|
||||
<AssemblyName>Microsoft.AspNet.WebHooks.Custom.SqlStorage</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<DocumentationFile>$(OutputPath)$(AssemblyName).xml</DocumentationFile>
|
||||
<RunCodeAnalysis>$(CodeAnalysis)</RunCodeAnalysis>
|
||||
<CodeAnalysisAdditionalOptions>/assemblyCompareMode:StrongNameIgnoringVersion</CodeAnalysisAdditionalOptions>
|
||||
<CodeAnalysisRuleSet>..\..\FxCop.ruleset</CodeAnalysisRuleSet>
|
||||
<DefineConstants>$(DefineConstants);ASPNETWEBHOOKS</DefineConstants>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.Cryptography.Internal, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.Cryptography.Internal.1.0.0-beta6\lib\net451\Microsoft.AspNet.Cryptography.Internal.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.DataProtection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.DataProtection.1.0.0-beta6\lib\net451\Microsoft.AspNet.DataProtection.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.DataProtection.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.DataProtection.Abstractions.1.0.0-beta6\lib\net451\Microsoft.AspNet.DataProtection.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Configuration, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Configuration.1.0.0-beta6\lib\net45\Microsoft.Framework.Configuration.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Configuration.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Configuration.Abstractions.1.0.0-beta6\lib\net45\Microsoft.Framework.Configuration.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Configuration.Binder, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Configuration.Binder.1.0.0-beta6\lib\net45\Microsoft.Framework.Configuration.Binder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.DependencyInjection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.DependencyInjection.1.0.0-beta5\lib\net45\Microsoft.Framework.DependencyInjection.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.DependencyInjection.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.DependencyInjection.Abstractions.1.0.0-beta6\lib\net45\Microsoft.Framework.DependencyInjection.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Logging.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Logging.Abstractions.1.0.0-beta6\lib\net45\Microsoft.Framework.Logging.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.OptionsModel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.OptionsModel.1.0.0-beta6\lib\net45\Microsoft.Framework.OptionsModel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Common\CommonAssemblyInfo.cs">
|
||||
<Link>Properties\CommonAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="Migrations\201510210452218_WebHooksInitialDb.cs" />
|
||||
<Compile Include="Migrations\201510210452218_WebHooksInitialDb.Designer.cs">
|
||||
<DependentUpon>201510210452218_WebHooksInitialDb.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\Configuration.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\SqlStorageResources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>SqlStorageResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Storage\Registration.cs" />
|
||||
<Compile Include="Storage\WebHookContext.cs" />
|
||||
<Compile Include="Extensions\HttpConfigurationExtensions.cs" />
|
||||
<Compile Include="WebHooks\SqlWebHookStore.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Migrations\201510210452218_WebHooksInitialDb.resx">
|
||||
<DependentUpon>201510210452218_WebHooksInitialDb.cs</DependentUpon>
|
||||
<ExcludeFromStyleCop>True</ExcludeFromStyleCop>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\SqlStorageResources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>SqlStorageResources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Microsoft.AspNet.WebHooks.Custom.SqlStorage.nuspec" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.WebHooks.Common\Microsoft.AspNet.WebHooks.Common.csproj">
|
||||
<Project>{f7dd0935-6320-4efc-9464-d5a2d2b8c2f7}</Project>
|
||||
<Name>Microsoft.AspNet.WebHooks.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.WebHooks.Custom\Microsoft.AspNet.WebHooks.Custom.csproj">
|
||||
<Project>{d4d210c6-3283-4d1d-806e-8717d8f51179}</Project>
|
||||
<Name>Microsoft.AspNet.WebHooks.Custom</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CodeAnalysisDictionary Include="..\..\CustomDictionary.xml">
|
||||
<Link>CustomDictionary.xml</Link>
|
||||
</CodeAnalysisDictionary>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets" Condition="Exists('..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable 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\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets'))" />
|
||||
</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>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>$id$</id>
|
||||
<version>$symversion$</version>
|
||||
<title>Microsoft ASP.NET Custom WebHooks SQL Module</title>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>Microsoft, aspnet</owners>
|
||||
<licenseUrl>http://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm</licenseUrl>
|
||||
<projectUrl>http://www.asp.net/</projectUrl>
|
||||
<iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
|
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||
<description>
|
||||
This package provides support for persisting your custom WebHooks registrations in a SQL database.
|
||||
</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>© Microsoft Corporation. All rights reserved</copyright>
|
||||
<tags>Microsoft AspNet WebApi AspNetWebApi WebHooks</tags>
|
||||
</metadata>
|
||||
</package>
|
29
src/Microsoft.AspNet.WebHooks.Custom.SqlStorage/Migrations/201510210452218_WebHooksInitialDb.Designer.cs
сгенерированный
Normal file
29
src/Microsoft.AspNet.WebHooks.Custom.SqlStorage/Migrations/201510210452218_WebHooksInitialDb.Designer.cs
сгенерированный
Normal file
|
@ -0,0 +1,29 @@
|
|||
// <auto-generated />
|
||||
namespace Microsoft.AspNet.WebHooks.Custom.SqlStorage.Migrations
|
||||
{
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Data.Entity.Migrations;
|
||||
using System.Data.Entity.Migrations.Infrastructure;
|
||||
using System.Resources;
|
||||
|
||||
[GeneratedCode("EntityFramework.Migrations", "6.1.3-40302")]
|
||||
public sealed partial class WebHooksInitialDb : IMigrationMetadata
|
||||
{
|
||||
private readonly ResourceManager Resources = new ResourceManager(typeof(WebHooksInitialDb));
|
||||
|
||||
string IMigrationMetadata.Id
|
||||
{
|
||||
get { return "201510210452218_WebHooksInitialDb"; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Source
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
string IMigrationMetadata.Target
|
||||
{
|
||||
get { return Resources.GetString("Target"); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Data.Entity.Migrations;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks.Custom.SqlStorage.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a <see cref="DbMigration"/> class for managing WebHook registrations.
|
||||
/// </summary>
|
||||
public partial class WebHooksInitialDb : DbMigration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override void Up()
|
||||
{
|
||||
CreateTable(
|
||||
"WebHooks.WebHooks",
|
||||
c => new
|
||||
{
|
||||
User = c.String(nullable: false, maxLength: 256),
|
||||
Id = c.String(nullable: false, maxLength: 256),
|
||||
ProtectedData = c.String(nullable: false),
|
||||
RowVer = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion"),
|
||||
})
|
||||
.PrimaryKey(t => new { t.User, t.Id });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Down()
|
||||
{
|
||||
DropTable("WebHooks.WebHooks");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Target" xml:space="preserve">
|
||||
<value>H4sIAAAAAAAEAM1Y3W7bNhS+H7B3EHi1AamZpNiQBnKL1Em2oHUSRGl2TUvHDlGK1EgqtZ5tF3ukvUIP9W/Kf8m6ofCNRR5+5/87lP756+/w3TIVwRNow5Uck6PRIQlAxirhcjEmuZ2/OiHv3v74Q3iRpMvgoZF77eTwpDRj8mhtdkqpiR8hZWaU8lgro+Z2FKuUskTR48PDN/ToiAJCEMQKgvAul5anUD7g40TJGDKbMzFVCQhTr+NOVKIG1ywFk7EYxmTa4p+Z7Brs6A+Y/a7UZ0OCM8EZGhSBmJOASakss2ju6ScDkdVKLqIMF5i4LzJAuTkTBmo3TjvxfT06PHYe0e5gAxXnxqr0mYBHr+sQUf/4iwJN2hBiEC8w2LZwXpeBHJM7WHBjdQ3vKzydCO2Et8R61Ec4CDbLTUrsUfSniKzSbAEHbRFhrbnfQTDJhc01jCXkiCgOgtt8Jnj8AYp79RnkWOZC9P1Bj3BvZQGXbrXKQNviDua1l5h2TQK6W/Aq8cVC6mtoj62AV2HC4sJ2IcGULT+CXNjHMTn+5VcSXPIlJM1KXW2fJMfuwkNW5/h4jb6xmYB2n27V6iz9v3Xio4XYQnLOLNuiHv/+F+rv1JeHLtTvuWS6IIFjjFxrpKpiWmKXilfsOVlvzUB9r/BdjcJvIAELG5JbZi1obN+JSrPcglclIe36athtaKBlHJFqN+qOcMuwtGuaDguq7jtTR2o1LBVsBHZNDyP3dbZUBDha7fF1hrcmdnRLK75teJluIOZwyrIM898j6noliCqWnryKns9baYVBY7OGvlprW00VoXi7LlsJXHJtrKvXGXMpniTpQMxLyIZgN8rWxdwnli4FzSn3vzq5H5P6kF1cL9HVFKQtvYbWPI/KB8fLCcoE02vZa6JEnsptZLkZwTFR//yQQ7ed9jilD+Rt7Y/ZEEUfrFkbooTUi6yfTTpIpzch/BrZ1mG+SKu97TSvo8K6unffhwblXomQAMPzxBNX6lFhLKQjJ+Am8URw9LcTmDLJ52BsNW0JduOJd5f6fu411JhEPONy8z1fG+QT0/Ej08Mh/uJbwTeDXDv0G/SfUrb8+V8Ocq2+1G8dJNg5drdqet4cHk6H/cfszilbtV47W3As31dmdwsvHMRDOghp/yUqPAfDFx2Ee6WSmEA0qwNtZK7kXDXJQU/7FjUiXu6mYFmCATvTls9ZbHE7BmPKK+ADEzmKXKQzSK7kTW4xaWfGQDoTRd/fkG7XX942Vm0Ob7Jy1H4LF9BMji7AjXyfc5G0dl+uqagNEK526jJFqyKXdlgULdK1knsC1eE7hwxkglx8D2kmEMzcyIg9wUtsQ2L5CAsWFw2rbwbZnYjVsIfnnC00S02N0Z13Hwao+zLw9iuAgaFKSxAAAA==</value>
|
||||
</data>
|
||||
<data name="DefaultSchema" xml:space="preserve">
|
||||
<value>WebHooks</value>
|
||||
</data>
|
||||
</root>
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information
|
||||
|
||||
using System.Data.Entity.Migrations;
|
||||
using Microsoft.AspNet.WebHooks.Storage;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks.Custom.SqlStorage.Migrations
|
||||
{
|
||||
internal sealed class Configuration : DbMigrationsConfiguration<WebHookContext>
|
||||
{
|
||||
public Configuration()
|
||||
{
|
||||
AutomaticMigrationsEnabled = false;
|
||||
}
|
||||
|
||||
protected override void Seed(WebHookContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNet.WebHooks.Custom.SqlStorage.Test")]
|
117
src/Microsoft.AspNet.WebHooks.Custom.SqlStorage/Properties/SqlStorageResources.Designer.cs
сгенерированный
Normal file
117
src/Microsoft.AspNet.WebHooks.Custom.SqlStorage/Properties/SqlStorageResources.Designer.cs
сгенерированный
Normal file
|
@ -0,0 +1,117 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SqlStorageResources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal SqlStorageResources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNet.WebHooks.Properties.SqlStorageResources", typeof(SqlStorageResources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The '{0}' could not be retrieved from Azure Table store: {1}.
|
||||
/// </summary>
|
||||
internal static string AzureStore_BadWebHook {
|
||||
get {
|
||||
return ResourceManager.GetString("AzureStore_BadWebHook", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No entry was found with partition key '{0}' and row key '{1}'..
|
||||
/// </summary>
|
||||
internal static string AzureStore_NotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("AzureStore_NotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Concurrency failure during '{0}' operation: '{1}'..
|
||||
/// </summary>
|
||||
internal static string SqlStore_ConcurrencyError {
|
||||
get {
|
||||
return ResourceManager.GetString("SqlStore_ConcurrencyError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please provide an Azure Table Storage connection string with name '{0}' in the configuration string section of the 'Web.Config' file..
|
||||
/// </summary>
|
||||
internal static string SqlStore_NoConnectionString {
|
||||
get {
|
||||
return ResourceManager.GetString("SqlStore_NoConnectionString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to General error during '{0}' operation: '{1}'..
|
||||
/// </summary>
|
||||
internal static string SqlStore_OperationFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("SqlStore_OperationFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Operation '{0}' failed with error: '{1}'..
|
||||
/// </summary>
|
||||
internal static string SqlStore_SqlOperationFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("SqlStore_SqlOperationFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AzureStore_BadWebHook" xml:space="preserve">
|
||||
<value>The '{0}' could not be retrieved from Azure Table store: {1}</value>
|
||||
</data>
|
||||
<data name="AzureStore_NotFound" xml:space="preserve">
|
||||
<value>No entry was found with partition key '{0}' and row key '{1}'.</value>
|
||||
</data>
|
||||
<data name="SqlStore_ConcurrencyError" xml:space="preserve">
|
||||
<value>Concurrency failure during '{0}' operation: '{1}'.</value>
|
||||
</data>
|
||||
<data name="SqlStore_NoConnectionString" xml:space="preserve">
|
||||
<value>Please provide an Azure Table Storage connection string with name '{0}' in the configuration string section of the 'Web.Config' file.</value>
|
||||
</data>
|
||||
<data name="SqlStore_OperationFailed" xml:space="preserve">
|
||||
<value>General error during '{0}' operation: '{1}'.</value>
|
||||
</data>
|
||||
<data name="SqlStore_SqlOperationFailed" xml:space="preserve">
|
||||
<value>Operation '{0}' failed with error: '{1}'.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks.Storage
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the WebHook registration data model for rows stored in SQL.
|
||||
/// </summary>
|
||||
[Table("WebHooks")]
|
||||
public class Registration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the user ID for this WebHook registration.
|
||||
/// </summary>
|
||||
[Key]
|
||||
[StringLength(256)]
|
||||
[Column(Order = 0)]
|
||||
public string User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of this WebHook registration.
|
||||
/// </summary>
|
||||
[Key]
|
||||
[StringLength(256)]
|
||||
[Column(Order = 1)]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data included in this WebHook registration. Note that this is encrypted
|
||||
/// as it contains sensitive information.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string ProtectedData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a unique row version.
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "This is the pattern for row version.")]
|
||||
[Timestamp]
|
||||
public byte[] RowVer { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information
|
||||
|
||||
using System;
|
||||
using System.Data.Entity;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks.Storage
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a <see cref="DbContext"/> which contains the set of WebHook <see cref="Registration"/> instances.
|
||||
/// </summary>
|
||||
public class WebHookContext : DbContext
|
||||
{
|
||||
internal const string ConnectionStringName = "MS_SqlStoreConnectionString";
|
||||
private const string ConnectionStringNameParameter = "name=" + ConnectionStringName;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebHookContext"/> class.
|
||||
/// </summary>
|
||||
public WebHookContext() : base(ConnectionStringNameParameter)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current collection of <see cref="Registration"/> instances.
|
||||
/// </summary>
|
||||
public virtual DbSet<Registration> Registrations { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnModelCreating(DbModelBuilder modelBuilder)
|
||||
{
|
||||
if (modelBuilder == null)
|
||||
{
|
||||
throw new ArgumentNullException("modelBuilder");
|
||||
}
|
||||
|
||||
modelBuilder.HasDefaultSchema("WebHooks");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,345 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Entity;
|
||||
using System.Data.Entity.Core;
|
||||
using System.Data.Entity.Infrastructure;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DataProtection;
|
||||
using Microsoft.AspNet.WebHooks.Config;
|
||||
using Microsoft.AspNet.WebHooks.Diagnostics;
|
||||
using Microsoft.AspNet.WebHooks.Properties;
|
||||
using Microsoft.AspNet.WebHooks.Storage;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IWebHookStore"/> storing registered WebHooks in Microsoft SQL Server.
|
||||
/// </summary>
|
||||
[CLSCompliant(false)]
|
||||
public class SqlWebHookStore : WebHookStore
|
||||
{
|
||||
private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings() { Formatting = Formatting.None };
|
||||
private readonly IDataProtector _protector;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SqlWebHookStore"/> class with the given <paramref name="settings"/>,
|
||||
/// <paramref name="protector"/>, and <paramref name="logger"/>.
|
||||
/// </summary>
|
||||
public SqlWebHookStore(SettingsDictionary settings, IDataProtector protector, ILogger logger)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
throw new ArgumentNullException("settings");
|
||||
}
|
||||
if (protector == null)
|
||||
{
|
||||
throw new ArgumentNullException("protector");
|
||||
}
|
||||
if (logger == null)
|
||||
{
|
||||
throw new ArgumentNullException("logger");
|
||||
}
|
||||
|
||||
CheckSqlStorageConnectionString(settings);
|
||||
_protector = protector;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<WebHook>> GetAllWebHooksAsync(string user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
user = NormalizeKey(user);
|
||||
|
||||
try
|
||||
{
|
||||
using (var context = new WebHookContext())
|
||||
{
|
||||
var registrations = await context.Registrations.Where(r => r.User == user).ToArrayAsync();
|
||||
var collection = new List<WebHook>();
|
||||
foreach (var registration in registrations)
|
||||
{
|
||||
collection.Add(ConvertFromRegistration(registration));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_OperationFailed, "Get", ex.Message);
|
||||
_logger.Error(msg, ex);
|
||||
throw new InvalidOperationException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<WebHook> LookupWebHookAsync(string user, string id)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (id == null)
|
||||
{
|
||||
throw new ArgumentNullException("id");
|
||||
}
|
||||
|
||||
user = NormalizeKey(user);
|
||||
id = NormalizeKey(id);
|
||||
|
||||
try
|
||||
{
|
||||
using (var context = new WebHookContext())
|
||||
{
|
||||
var registration = await context.Registrations.Where(r => r.User == user && r.Id == id).FirstOrDefaultAsync();
|
||||
if (registration != null)
|
||||
{
|
||||
return ConvertFromRegistration(registration);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_OperationFailed, "Lookup", ex.Message);
|
||||
_logger.Error(msg, ex);
|
||||
throw new InvalidOperationException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<StoreResult> InsertWebHookAsync(string user, WebHook webHook)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (webHook == null)
|
||||
{
|
||||
throw new ArgumentNullException("webHook");
|
||||
}
|
||||
|
||||
user = NormalizeKey(user);
|
||||
|
||||
try
|
||||
{
|
||||
using (var context = new WebHookContext())
|
||||
{
|
||||
var registration = ConvertToRegistration(user, webHook);
|
||||
context.Registrations.Attach(registration);
|
||||
context.Entry(registration).State = EntityState.Added;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
catch (DbUpdateException uex)
|
||||
{
|
||||
string error = uex.GetBaseException().Message;
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_SqlOperationFailed, "Insert", error);
|
||||
_logger.Error(msg, uex);
|
||||
return StoreResult.Conflict;
|
||||
}
|
||||
catch (OptimisticConcurrencyException ocex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_ConcurrencyError, "Insert", ocex.Message);
|
||||
}
|
||||
catch (SqlException sqlex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_SqlOperationFailed, "Insert", sqlex.Message);
|
||||
_logger.Error(msg, sqlex);
|
||||
return StoreResult.OperationError;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_OperationFailed, "Insert", ex.Message);
|
||||
_logger.Error(msg, ex);
|
||||
return StoreResult.InternalError;
|
||||
}
|
||||
return StoreResult.Success;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<StoreResult> UpdateWebHookAsync(string user, WebHook webHook)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (webHook == null)
|
||||
{
|
||||
throw new ArgumentNullException("webHook");
|
||||
}
|
||||
|
||||
user = NormalizeKey(user);
|
||||
|
||||
try
|
||||
{
|
||||
using (var context = new WebHookContext())
|
||||
{
|
||||
var registration = await context.Registrations.Where(r => r.User == user && r.Id == webHook.Id).FirstOrDefaultAsync();
|
||||
if (registration == null)
|
||||
{
|
||||
return StoreResult.NotFound;
|
||||
}
|
||||
UpdateRegistrationFromWebHook(user, webHook, registration);
|
||||
context.Entry(registration).State = EntityState.Modified;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
catch (OptimisticConcurrencyException ocex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_ConcurrencyError, "Update", ocex.Message);
|
||||
_logger.Error(msg, ocex);
|
||||
return StoreResult.Conflict;
|
||||
}
|
||||
catch (SqlException sqlex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_SqlOperationFailed, "Update", sqlex.Message);
|
||||
_logger.Error(msg, sqlex);
|
||||
return StoreResult.OperationError;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_OperationFailed, "Update", ex.Message);
|
||||
_logger.Error(msg, ex);
|
||||
return StoreResult.InternalError;
|
||||
}
|
||||
return StoreResult.Success;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<StoreResult> DeleteWebHookAsync(string user, string id)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (id == null)
|
||||
{
|
||||
throw new ArgumentNullException("id");
|
||||
}
|
||||
|
||||
user = NormalizeKey(user);
|
||||
|
||||
try
|
||||
{
|
||||
using (var context = new WebHookContext())
|
||||
{
|
||||
var match = await context.Registrations.Where(r => r.User == user && r.Id == id).FirstOrDefaultAsync();
|
||||
if (match == null)
|
||||
{
|
||||
return StoreResult.NotFound;
|
||||
}
|
||||
context.Entry(match).State = EntityState.Deleted;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
catch (OptimisticConcurrencyException ocex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_ConcurrencyError, "Delete", ocex.Message);
|
||||
_logger.Error(msg, ocex);
|
||||
return StoreResult.Conflict;
|
||||
}
|
||||
catch (SqlException sqlex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_SqlOperationFailed, "Delete", sqlex.Message);
|
||||
_logger.Error(msg, sqlex);
|
||||
return StoreResult.OperationError;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_OperationFailed, "Delete", ex.Message);
|
||||
_logger.Error(msg, ex);
|
||||
return StoreResult.InternalError;
|
||||
}
|
||||
return StoreResult.Success;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task DeleteAllWebHooksAsync(string user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
user = NormalizeKey(user);
|
||||
|
||||
try
|
||||
{
|
||||
using (var context = new WebHookContext())
|
||||
{
|
||||
var matches = await context.Registrations.Where(r => r.User == user).ToArrayAsync();
|
||||
foreach (var m in matches)
|
||||
{
|
||||
context.Entry(m).State = EntityState.Deleted;
|
||||
}
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_OperationFailed, "DeleteAll", ex.Message);
|
||||
_logger.Error(msg, ex);
|
||||
throw new InvalidOperationException(msg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string CheckSqlStorageConnectionString(SettingsDictionary settings)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
throw new ArgumentNullException("settings");
|
||||
}
|
||||
|
||||
ConnectionSettings connection;
|
||||
if (!settings.Connections.TryGetValue(WebHookContext.ConnectionStringName, out connection) || connection == null || string.IsNullOrEmpty(connection.ConnectionString))
|
||||
{
|
||||
string msg = string.Format(CultureInfo.CurrentCulture, SqlStorageResources.SqlStore_NoConnectionString, WebHookContext.ConnectionStringName);
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
return connection.ConnectionString;
|
||||
}
|
||||
|
||||
private WebHook ConvertFromRegistration(Registration registration)
|
||||
{
|
||||
string content = _protector.Unprotect(registration.ProtectedData);
|
||||
WebHook webHook = JsonConvert.DeserializeObject<WebHook>(content, _serializerSettings);
|
||||
return webHook;
|
||||
}
|
||||
|
||||
private Registration ConvertToRegistration(string user, WebHook webHook)
|
||||
{
|
||||
string content = JsonConvert.SerializeObject(webHook, _serializerSettings);
|
||||
string protectedData = _protector.Protect(content);
|
||||
var registration = new Registration
|
||||
{
|
||||
User = user,
|
||||
Id = webHook.Id,
|
||||
ProtectedData = protectedData
|
||||
};
|
||||
return registration;
|
||||
}
|
||||
|
||||
private void UpdateRegistrationFromWebHook(string user, WebHook webHook, Registration registration)
|
||||
{
|
||||
registration.User = user;
|
||||
registration.Id = webHook.Id;
|
||||
string content = JsonConvert.SerializeObject(webHook, _serializerSettings);
|
||||
string protectedData = _protector.Protect(content);
|
||||
registration.ProtectedData = protectedData;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="EntityFramework" version="6.1.1" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.Cryptography.Internal" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.DataProtection" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.DataProtection.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Configuration" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Configuration.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Configuration.Binder" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.DependencyInjection" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.DependencyInjection.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Logging.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.OptionsModel" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net451" />
|
||||
</packages>
|
|
@ -69,6 +69,7 @@
|
|||
<Compile Include="WebHooks\WebHook.cs" />
|
||||
<Compile Include="WebHooks\WebHookFilter.cs" />
|
||||
<Compile Include="WebHooks\WebHookFilterManager.cs" />
|
||||
<Compile Include="WebHooks\WebHookStore.cs" />
|
||||
<Compile Include="WebHooks\WebHookUser.cs" />
|
||||
<Compile Include="WebHooks\WebHookManager.cs" />
|
||||
<Compile Include="WebHooks\WebHookWorkItem.cs" />
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an abstract <see cref="IWebHookStore"/> implementation which can be used to base other implementations on.
|
||||
/// </summary>
|
||||
public abstract class WebHookStore : IWebHookStore
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebHookStore"/> class.
|
||||
/// </summary>
|
||||
protected WebHookStore()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task<ICollection<WebHook>> GetAllWebHooksAsync(string user);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<ICollection<WebHook>> QueryWebHooksAsync(string user, IEnumerable<string> actions)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (actions == null)
|
||||
{
|
||||
throw new ArgumentNullException("actions");
|
||||
}
|
||||
|
||||
ICollection<WebHook> webHooks = await GetAllWebHooksAsync(user);
|
||||
ICollection<WebHook> matches = new List<WebHook>();
|
||||
foreach (WebHook webHook in webHooks)
|
||||
{
|
||||
if (webHook.IsPaused)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (string action in actions)
|
||||
{
|
||||
if (webHook.MatchesAction(action))
|
||||
{
|
||||
matches.Add(webHook);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task<WebHook> LookupWebHookAsync(string user, string id);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task<StoreResult> InsertWebHookAsync(string user, WebHook webHook);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task<StoreResult> UpdateWebHookAsync(string user, WebHook webHook);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task<StoreResult> DeleteWebHookAsync(string user, string id);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Task DeleteAllWebHooksAsync(string user);
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a given key to ensure consistent lookups.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to normalize.</param>
|
||||
/// <returns>The normalized key.</returns>
|
||||
protected virtual string NormalizeKey(string key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
return key.ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</configSections>
|
||||
<appSettings></appSettings>
|
||||
<connectionStrings>
|
||||
<add name="MS_SqlStoreConnectionString" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=WebHooks-20151029053732;Integrated Security=True"
|
||||
providerName="System.Data.SqlClient" />
|
||||
</connectionStrings>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<entityFramework>
|
||||
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
|
||||
<parameters>
|
||||
<parameter value="mssqllocaldb" />
|
||||
</parameters>
|
||||
</defaultConnectionFactory>
|
||||
<providers>
|
||||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
|
||||
</providers>
|
||||
</entityFramework>
|
||||
</configuration>
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Web.Http;
|
||||
using Microsoft.AspNet.WebHooks.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks
|
||||
{
|
||||
public class HttpConfigurationExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Initialize_SetsStore()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration config = new HttpConfiguration();
|
||||
|
||||
// Act
|
||||
config.InitializeCustomWebHooksSqlStorage();
|
||||
IWebHookStore actual = CustomServices.GetStore();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<SqlWebHookStore>(actual);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\xunit.runner.visualstudio.2.0.1\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\..\packages\xunit.runner.visualstudio.2.0.1\build\net20\xunit.runner.visualstudio.props')" />
|
||||
<Import Project="..\..\packages\xunit.core.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props" Condition="Exists('..\..\packages\xunit.core.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props')" />
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),WebHooks.sln))\tools\WebHooks.settings.targets" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{CCE7ADB5-7335-4F7D-A34D-0B7CA1D3141F}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.AspNet.WebHooks</RootNamespace>
|
||||
<AssemblyName>Microsoft.AspNet.WebHooks.Custom.SqlStorage.Test</AssemblyName>
|
||||
<OutputPath>..\..\bin\$(Configuration)\Test\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<RunCodeAnalysis>$(CodeAnalysis)</RunCodeAnalysis>
|
||||
<CodeAnalysisAdditionalOptions>/assemblyCompareMode:StrongNameIgnoringVersion</CodeAnalysisAdditionalOptions>
|
||||
<CodeAnalysisRuleSet>..\..\FxCopTest.ruleset</CodeAnalysisRuleSet>
|
||||
<DefineConstants>$(DefineConstants);ASPNETWEBHOOKS</DefineConstants>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.Cryptography.Internal, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.Cryptography.Internal.1.0.0-beta6\lib\net451\Microsoft.AspNet.Cryptography.Internal.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.DataProtection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.DataProtection.1.0.0-beta6\lib\net451\Microsoft.AspNet.DataProtection.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.DataProtection.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.DataProtection.Abstractions.1.0.0-beta6\lib\net451\Microsoft.AspNet.DataProtection.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Configuration, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Configuration.1.0.0-beta6\lib\net45\Microsoft.Framework.Configuration.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Configuration.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Configuration.Abstractions.1.0.0-beta6\lib\net45\Microsoft.Framework.Configuration.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Configuration.Binder, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Configuration.Binder.1.0.0-beta6\lib\net45\Microsoft.Framework.Configuration.Binder.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.DependencyInjection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.DependencyInjection.1.0.0-beta5\lib\net45\Microsoft.Framework.DependencyInjection.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.DependencyInjection.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.DependencyInjection.Abstractions.1.0.0-beta6\lib\net45\Microsoft.Framework.DependencyInjection.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.Logging.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.Logging.Abstractions.1.0.0-beta6\lib\net45\Microsoft.Framework.Logging.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Framework.OptionsModel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Framework.OptionsModel.1.0.0-beta6\lib\net45\Microsoft.Framework.OptionsModel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.2.1502.911, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.2\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.2\lib\net45\System.Web.Http.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<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.0\lib\net35\xunit.abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="xunit.assert, Version=2.0.0.2929, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\xunit.assert.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="xunit.core, Version=2.0.0.2929, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\xunit.extensibility.core.2.0.0\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Extensions\HttpConfigurationExtensionsTests.cs" />
|
||||
<Compile Include="WebHooks\SqlWebHookStoreTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Src\Microsoft.AspNet.WebHooks.Common\Microsoft.AspNet.WebHooks.Common.csproj">
|
||||
<Project>{f7dd0935-6320-4efc-9464-d5a2d2b8c2f7}</Project>
|
||||
<Name>Microsoft.AspNet.WebHooks.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNet.WebHooks.Custom.SqlStorage\Microsoft.AspNet.WebHooks.Custom.SqlStorage.csproj">
|
||||
<Project>{eac99e25-f698-41b2-8671-740d642781ab}</Project>
|
||||
<Name>Microsoft.AspNet.WebHooks.Custom.SqlStorage</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Src\Microsoft.AspNet.WebHooks.Custom\Microsoft.AspNet.WebHooks.Custom.csproj">
|
||||
<Project>{d4d210c6-3283-4d1d-806e-8717d8f51179}</Project>
|
||||
<Name>Microsoft.AspNet.WebHooks.Custom</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.TestUtilities\Microsoft.TestUtilities.csproj">
|
||||
<Project>{608b1d09-e4de-4dba-8dbf-7758003988f0}</Project>
|
||||
<Name>Microsoft.TestUtilities</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.WebHooks.Custom.Test\Microsoft.AspNet.WebHooks.Custom.Test.csproj">
|
||||
<Project>{acebdb96-642f-4b5d-8963-4f67bd927d76}</Project>
|
||||
<Name>Microsoft.AspNet.WebHooks.Custom.Test</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CodeAnalysisDictionary Include="..\..\CustomDictionary.xml">
|
||||
<Link>CustomDictionary.xml</Link>
|
||||
</CodeAnalysisDictionary>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Storage\" />
|
||||
</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. Enable 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.core.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.core.2.0.0\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.props'))" />
|
||||
<Error Condition="!Exists('..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\xunit.runner.visualstudio.2.0.1\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.runner.visualstudio.2.0.1\build\net20\xunit.runner.visualstudio.props'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets" Condition="Exists('..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets')" />
|
||||
<!-- 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>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
[assembly: CLSCompliant(false)]
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Configuration;
|
||||
using System.Data.Entity;
|
||||
using System.Data.Entity.Migrations;
|
||||
using System.Web.Http;
|
||||
using Microsoft.AspNet.WebHooks.Services;
|
||||
using Microsoft.AspNet.WebHooks.Storage;
|
||||
using Xunit;
|
||||
using EF = Microsoft.AspNet.WebHooks.Custom.SqlStorage.Migrations;
|
||||
|
||||
namespace Microsoft.AspNet.WebHooks
|
||||
{
|
||||
public class SqlWebHookStoreTests : WebHookStoreTest
|
||||
{
|
||||
public SqlWebHookStoreTests()
|
||||
: base(CreateStore())
|
||||
{
|
||||
}
|
||||
|
||||
private static IWebHookStore CreateStore()
|
||||
{
|
||||
// Delete any existing DB
|
||||
string connectionString = ConfigurationManager.ConnectionStrings[WebHookContext.ConnectionStringName].ConnectionString;
|
||||
Database.Delete(connectionString);
|
||||
|
||||
// Initialize DB using code first migration
|
||||
var dbConfig = new EF.Configuration();
|
||||
var migrator = new DbMigrator(dbConfig);
|
||||
migrator.Update();
|
||||
|
||||
HttpConfiguration config = new HttpConfiguration();
|
||||
config.InitializeCustomWebHooksSqlStorage();
|
||||
IWebHookStore store = CustomServices.GetStore();
|
||||
Assert.IsType<SqlWebHookStore>(store);
|
||||
return store;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="EntityFramework" version="6.1.1" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.Cryptography.Internal" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.DataProtection" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.DataProtection.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Configuration" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Configuration.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Configuration.Binder" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.DependencyInjection" version="1.0.0-beta5" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.DependencyInjection.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.Logging.Abstractions" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Microsoft.Framework.OptionsModel" version="1.0.0-beta6" targetFramework="net451" />
|
||||
<package id="Moq" version="4.2.1502.0911" targetFramework="net45" />
|
||||
<package id="StyleCop.MSBuild" version="4.7.49.1" targetFramework="net451" developmentDependency="true" />
|
||||
<package id="xunit" version="2.0.0" targetFramework="net45" />
|
||||
<package id="xunit.abstractions" version="2.0.0" targetFramework="net45" />
|
||||
<package id="xunit.assert" version="2.0.0" targetFramework="net45" />
|
||||
<package id="xunit.core" version="2.0.0" targetFramework="net45" />
|
||||
<package id="xunit.extensibility.core" version="2.0.0" targetFramework="net45" />
|
||||
<package id="xunit.runner.visualstudio" version="2.0.1" targetFramework="net451" />
|
||||
</packages>
|
Загрузка…
Ссылка в новой задаче