From bdf69b0d0c7aafb021c64140bc619d276a5f83d4 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Thu, 19 Dec 2013 11:38:05 -0800 Subject: [PATCH] Initial commit --- .gitignore | 17 + AspNetAbstractions.sln | 52 +++ Sakefile.shade | 66 +++ build.cmd | 12 + build.sh | 6 + .../HttpContextBase.cs | 10 + .../HttpRequestBase.cs | 18 + .../HttpResponseBase.cs | 13 + src/Microsoft.AspNet.Abstractions/IBuilder.cs | 15 + .../Microsoft.AspNet.Abstractions.csproj | 57 +++ .../Microsoft.AspNet.Abstractions.nuspec | 22 + .../PathString.cs | 232 +++++++++++ .../Properties/AssemblyInfo.cs | 36 ++ .../QueryString.cs | 142 +++++++ .../RequestDelegate.cs | 6 + .../FeatureContainer.cs | 86 ++++ .../IFeatureContainer.cs | 13 + .../Implementation/Converter.cs | 384 ++++++++++++++++++ .../Microsoft.AspNet.FeatureModel.csproj | 54 +++ .../Microsoft.AspNet.FeatureModel.nuspec | 22 + .../ObjectFeatureContainer.cs | 50 +++ .../Properties/AssemblyInfo.cs | 36 ++ .../HttpEnvironmentBase.cs | 8 + .../HttpEnvironmentExtensions.cs | 10 + .../IHttpEnvironment.cs | 8 + .../Microsoft.AspNet.HttpEnvironment.csproj | 59 +++ .../Microsoft.AspNet.HttpEnvironment.nuspec | 22 + .../Properties/AssemblyInfo.cs | 36 ++ .../IHttpApplicationInformation.cs | 14 + .../IHttpBuffering.cs | 8 + .../IHttpConnection.cs | 13 + .../IHttpRequest.cs | 19 + .../IHttpResponse.cs | 15 + .../IHttpSendFile.cs | 10 + .../IHttpTransportLayerSecurity.cs | 11 + .../IHttpWebSocketAccept.cs | 11 + .../Microsoft.AspNet.HttpFeature.csproj | 64 +++ .../Microsoft.AspNet.HttpFeature.nuspec | 22 + .../Properties/AssemblyInfo.cs | 36 ++ .../Security/IAuthenticationChallenge.cs | 10 + .../Security/IAuthenticationDescription.cs | 9 + .../Security/IAuthenticationResult.cs | 12 + .../Security/IAuthenticationSignIn.cs | 11 + .../Security/IAuthenticationSignOut.cs | 9 + .../Security/IHttpAuthentication.cs | 18 + .../BuilderTests.cs | 24 ++ ...Microsoft.AspNet.PipelineCore.Tests.csproj | 79 ++++ .../Properties/AssemblyInfo.cs | 36 ++ .../packages.config | 6 + src/Microsoft.AspNet.PipelineCore/Builder.cs | 93 +++++ .../HttpContext.cs | 44 ++ .../HttpRequest.cs | 74 ++++ .../HttpResponse.cs | 43 ++ .../Microsoft.AspNet.PipelineCore.csproj | 75 ++++ .../Microsoft.AspNet.PipelineCore.nuspec | 22 + .../Owin/OwinConstants.cs | 174 ++++++++ .../Owin/OwinHttpEnvironment.cs | 167 ++++++++ .../Properties/AssemblyInfo.cs | 36 ++ 58 files changed, 2657 insertions(+) create mode 100644 .gitignore create mode 100644 AspNetAbstractions.sln create mode 100644 Sakefile.shade create mode 100644 build.cmd create mode 100644 build.sh create mode 100644 src/Microsoft.AspNet.Abstractions/HttpContextBase.cs create mode 100644 src/Microsoft.AspNet.Abstractions/HttpRequestBase.cs create mode 100644 src/Microsoft.AspNet.Abstractions/HttpResponseBase.cs create mode 100644 src/Microsoft.AspNet.Abstractions/IBuilder.cs create mode 100644 src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.csproj create mode 100644 src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.nuspec create mode 100644 src/Microsoft.AspNet.Abstractions/PathString.cs create mode 100644 src/Microsoft.AspNet.Abstractions/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.Abstractions/QueryString.cs create mode 100644 src/Microsoft.AspNet.Abstractions/RequestDelegate.cs create mode 100644 src/Microsoft.AspNet.FeatureModel/FeatureContainer.cs create mode 100644 src/Microsoft.AspNet.FeatureModel/IFeatureContainer.cs create mode 100644 src/Microsoft.AspNet.FeatureModel/Implementation/Converter.cs create mode 100644 src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.csproj create mode 100644 src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.nuspec create mode 100644 src/Microsoft.AspNet.FeatureModel/ObjectFeatureContainer.cs create mode 100644 src/Microsoft.AspNet.FeatureModel/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentBase.cs create mode 100644 src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentExtensions.cs create mode 100644 src/Microsoft.AspNet.HttpEnvironment/IHttpEnvironment.cs create mode 100644 src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.csproj create mode 100644 src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.nuspec create mode 100644 src/Microsoft.AspNet.HttpEnvironment/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpApplicationInformation.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpBuffering.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpConnection.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpRequest.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpResponse.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpSendFile.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpTransportLayerSecurity.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/IHttpWebSocketAccept.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.csproj create mode 100644 src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.nuspec create mode 100644 src/Microsoft.AspNet.HttpFeature/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationChallenge.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationDescription.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationResult.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignIn.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignOut.cs create mode 100644 src/Microsoft.AspNet.HttpFeature/Security/IHttpAuthentication.cs create mode 100644 src/Microsoft.AspNet.PipelineCore.Tests/BuilderTests.cs create mode 100644 src/Microsoft.AspNet.PipelineCore.Tests/Microsoft.AspNet.PipelineCore.Tests.csproj create mode 100644 src/Microsoft.AspNet.PipelineCore.Tests/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.PipelineCore.Tests/packages.config create mode 100644 src/Microsoft.AspNet.PipelineCore/Builder.cs create mode 100644 src/Microsoft.AspNet.PipelineCore/HttpContext.cs create mode 100644 src/Microsoft.AspNet.PipelineCore/HttpRequest.cs create mode 100644 src/Microsoft.AspNet.PipelineCore/HttpResponse.cs create mode 100644 src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.csproj create mode 100644 src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.nuspec create mode 100644 src/Microsoft.AspNet.PipelineCore/Owin/OwinConstants.cs create mode 100644 src/Microsoft.AspNet.PipelineCore/Owin/OwinHttpEnvironment.cs create mode 100644 src/Microsoft.AspNet.PipelineCore/Properties/AssemblyInfo.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..5dc98f5c69 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +bin +obj +*.suo +*.user +_ReSharper.* +*.DS_Store +*.userprefs +*.pidb +*.vspx +*.psess +packages +target +artifacts +StyleCop.Cache +node_modules +*.snk +.nuget/NuGet.exe diff --git a/AspNetAbstractions.sln b/AspNetAbstractions.sln new file mode 100644 index 0000000000..2e07b4f2cb --- /dev/null +++ b/AspNetAbstractions.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Abstractions", "src\Microsoft.AspNet.Abstractions\Microsoft.AspNet.Abstractions.csproj", "{4E1520B1-01F4-481B-96A2-24067EAA52FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.FeatureModel", "src\Microsoft.AspNet.FeatureModel\Microsoft.AspNet.FeatureModel.csproj", "{A780873E-09F9-4E44-AE06-AF00C4E88E1E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.HttpEnvironment", "src\Microsoft.AspNet.HttpEnvironment\Microsoft.AspNet.HttpEnvironment.csproj", "{46D69EC9-7096-49D8-A184-A9BB5B2419A1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.HttpFeature", "src\Microsoft.AspNet.HttpFeature\Microsoft.AspNet.HttpFeature.csproj", "{42309978-0661-41D8-8654-39453265C5F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.PipelineCore", "src\Microsoft.AspNet.PipelineCore\Microsoft.AspNet.PipelineCore.csproj", "{A4D3E280-8838-4614-9B99-4874C3CBDF82}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.PipelineCore.Tests", "src\Microsoft.AspNet.PipelineCore.Tests\Microsoft.AspNet.PipelineCore.Tests.csproj", "{86942914-0334-4352-87ED-B971281C74E2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4E1520B1-01F4-481B-96A2-24067EAA52FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E1520B1-01F4-481B-96A2-24067EAA52FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E1520B1-01F4-481B-96A2-24067EAA52FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E1520B1-01F4-481B-96A2-24067EAA52FA}.Release|Any CPU.Build.0 = Release|Any CPU + {A780873E-09F9-4E44-AE06-AF00C4E88E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A780873E-09F9-4E44-AE06-AF00C4E88E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A780873E-09F9-4E44-AE06-AF00C4E88E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A780873E-09F9-4E44-AE06-AF00C4E88E1E}.Release|Any CPU.Build.0 = Release|Any CPU + {46D69EC9-7096-49D8-A184-A9BB5B2419A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46D69EC9-7096-49D8-A184-A9BB5B2419A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46D69EC9-7096-49D8-A184-A9BB5B2419A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46D69EC9-7096-49D8-A184-A9BB5B2419A1}.Release|Any CPU.Build.0 = Release|Any CPU + {42309978-0661-41D8-8654-39453265C5F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {42309978-0661-41D8-8654-39453265C5F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {42309978-0661-41D8-8654-39453265C5F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {42309978-0661-41D8-8654-39453265C5F9}.Release|Any CPU.Build.0 = Release|Any CPU + {A4D3E280-8838-4614-9B99-4874C3CBDF82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4D3E280-8838-4614-9B99-4874C3CBDF82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4D3E280-8838-4614-9B99-4874C3CBDF82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4D3E280-8838-4614-9B99-4874C3CBDF82}.Release|Any CPU.Build.0 = Release|Any CPU + {86942914-0334-4352-87ED-B971281C74E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86942914-0334-4352-87ED-B971281C74E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86942914-0334-4352-87ED-B971281C74E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86942914-0334-4352-87ED-B971281C74E2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sakefile.shade b/Sakefile.shade new file mode 100644 index 0000000000..56c6a45839 --- /dev/null +++ b/Sakefile.shade @@ -0,0 +1,66 @@ + +var PROJECT='AspNetAbstractions' +var VERSION='0.1.0' +var FULL_VERSION='${VERSION}' +var AUTHORS='${PROJECT} contributors' + +var BASE_DIR='${Directory.GetCurrentDirectory()}' +var TARGET_DIR='${Path.Combine(BASE_DIR, "target")}' +var BUILD_DIR='${Path.Combine(TARGET_DIR, "build")}' +var TEST_DIR='${Path.Combine(TARGET_DIR, "test")}' + +default SRC='.' +default BUILD_PROJECTS='${Files.Include(SRC+"/**/*.csproj")}' +default TEST_PROJECTS='${Files.Include(SRC+"/**/*.Tests.csproj")}' + +use namespace='System.Xml.Linq' + +-// include range of standard general targets. run "sake targets" to display +use-standard-lifecycle + +-// include sets of standard work targets. features include 'nuget,xunit,nunit' +use-standard-goals features='nuget,xunit' + +-// additional work targets are defined below + +#nuget-prepare target='package-prepare' description='Compile primary project' + for each='var projectFile in BUILD_PROJECTS.Except(TEST_PROJECTS)' + var outputDirName='${Path.GetFileNameWithoutExtension(projectFile)}' + + var outputDir='${Path.Combine(BUILD_DIR, outputDirName)}' + + copy sourceDir='${Path.GetDirectoryName(projectFile)}' include='*.nuspec' overwrite='${true}' + + var doc='${XDocument.Load(projectFile)}' + var ns='http://schemas.microsoft.com/developer/msbuild/2003' + var itemGroups='${doc.Elements(XName.Get("Project", ns)).Elements(XName.Get("ItemGroup", ns))}' + var compileItems='${itemGroups.Elements(XName.Get("Compile", ns))}' + var contentItems='${itemGroups.Elements(XName.Get("Content", ns))}' + var noneItems='${itemGroups.Elements(XName.Get("None", ns))}' + var razorItems='${contentItems.Union(noneItems).Where(x=>x.Attribute("Include").Value.EndsWith(".cshtml"))}' + + for each='var compileElt in compileItems.Union(razorItems)' + var linkElt='${compileElt.Elements(XName.Get("Link", ns)).SingleOrDefault()}' + + var sourceFile='${compileElt.Attribute("Include").Value}' + var targetFile='${linkElt == null ? sourceFile : linkElt.Value}' + + var sourceFull='${Path.Combine(Path.GetDirectoryName(projectFile), sourceFile)}' + var targetFull='${Path.Combine(outputDir, "src", targetFile)}' + directory create='${Path.GetDirectoryName(targetFull)}' + -File.Copy(sourceFull, targetFull, true); + +#nuget-package target='package' description='Create NuGet packages' + for each='var file in Files.Include(BUILD_DIR + "/**/*.nuspec")' + var baseName='${Path.GetFileNameWithoutExtension(file)}' + var nugetProperties='${new Dictionary { + {"id", baseName}, + {"authors", AUTHORS}, + {"title", baseName}, + {"description", baseName}, + {"licenseUrl", "about:blank"}, + {"projectUrl", "about:blank"}, + {"tags", "Katana"}, + }}' + var props='${string.Join(";", nugetProperties.Select(kv=>kv.Key+"="+kv.Value).ToArray())}' + nuget-pack nuspecFile='${file}' packageVersion='${FULL_VERSION}' outputDir='${TARGET_DIR}' extra='-NoPackageAnalysis -Properties "${props}"' diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000000..65dfe408fd --- /dev/null +++ b/build.cmd @@ -0,0 +1,12 @@ +@echo off +cd %~dp0 + +IF EXIST .nuget\NuGet.exe goto part2 +echo Downloading latest version of NuGet.exe... +mkdir .nuget +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "((new-object net.webclient).DownloadFile('https://nuget.org/nuget.exe', '.nuget\NuGet.exe'))" + +:part2 +set EnableNuGetPackageRestore=true +.nuget\NuGet.exe install Sake -version 0.2 -o packages +packages\Sake.0.2\tools\Sake.exe -I build -f Sakefile.shade %* diff --git a/build.sh b/build.sh new file mode 100644 index 0000000000..8a58a5e2a9 --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +export EnableNuGetPackageRestore=true +mono --runtime=v4.0 ".nuget/NuGet.exe" install Sake -pre -o packages +mono $(find packages/Sake.*/tools/Sake.exe|sort -r|head -n1) -f Sakefile.shade -I src/build "$@" + diff --git a/src/Microsoft.AspNet.Abstractions/HttpContextBase.cs b/src/Microsoft.AspNet.Abstractions/HttpContextBase.cs new file mode 100644 index 0000000000..e1ceb30048 --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/HttpContextBase.cs @@ -0,0 +1,10 @@ +namespace Microsoft.AspNet.Abstractions +{ + public abstract class HttpContextBase + { + // TODO - review IOwinContext for properties + + public abstract HttpRequestBase Request { get; } + public abstract HttpResponseBase Response { get; } + } +} diff --git a/src/Microsoft.AspNet.Abstractions/HttpRequestBase.cs b/src/Microsoft.AspNet.Abstractions/HttpRequestBase.cs new file mode 100644 index 0000000000..face559bdb --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/HttpRequestBase.cs @@ -0,0 +1,18 @@ +using System; +using System.IO; + +namespace Microsoft.AspNet.Abstractions +{ + public abstract class HttpRequestBase + { + // TODO - review IOwinRequest for properties + + public abstract HttpContextBase HttpContext { get; } + + public abstract Uri Uri { get; } + public abstract PathString PathBase { get; set; } + public abstract PathString Path { get; set; } + public abstract QueryString QueryString { get; set; } + public abstract Stream Body { get; set; } + } +} diff --git a/src/Microsoft.AspNet.Abstractions/HttpResponseBase.cs b/src/Microsoft.AspNet.Abstractions/HttpResponseBase.cs new file mode 100644 index 0000000000..518ea0355c --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/HttpResponseBase.cs @@ -0,0 +1,13 @@ +using System.IO; + +namespace Microsoft.AspNet.Abstractions +{ + public abstract class HttpResponseBase + { + // TODO - review IOwinResponse for completeness + + public abstract HttpContextBase HttpContext { get; } + public abstract int StatusCode { get; set; } + public abstract Stream Body { get; set; } + } +} diff --git a/src/Microsoft.AspNet.Abstractions/IBuilder.cs b/src/Microsoft.AspNet.Abstractions/IBuilder.cs new file mode 100644 index 0000000000..9016434cc3 --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/IBuilder.cs @@ -0,0 +1,15 @@ +using System; + +namespace Microsoft.AspNet.Abstractions +{ + public interface IBuilder + { + IBuilder Use(object middleware, params object[] args); + + IBuilder New(); + RequestDelegate Build(); + + object GetFeature(Type type); + void SetFeature(Type type, object feature); + } +} diff --git a/src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.csproj b/src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.csproj new file mode 100644 index 0000000000..4f5b7f0b33 --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.csproj @@ -0,0 +1,57 @@ + + + + + Debug + AnyCPU + {4E1520B1-01F4-481B-96A2-24067EAA52FA} + Library + Properties + Microsoft.AspNet.Abstractions + Microsoft.AspNet.Abstractions + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Microsoft.AspNet.Abstractions.XML + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.nuspec b/src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.nuspec new file mode 100644 index 0000000000..1b6a2894c7 --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/Microsoft.AspNet.Abstractions.nuspec @@ -0,0 +1,22 @@ + + + $id$ + $version$ + $authors$ + $authors$ + $licenseUrl$ + $projectUrl$ + true + $title$ + $title$ + $tags$ + + + + + + + + + + diff --git a/src/Microsoft.AspNet.Abstractions/PathString.cs b/src/Microsoft.AspNet.Abstractions/PathString.cs new file mode 100644 index 0000000000..8cfab5912d --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/PathString.cs @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +using System; +using System.Linq; + +namespace Microsoft.AspNet.Abstractions +{ + /// + /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string + /// + public struct PathString : IEquatable + { + /// + /// Represents the empty path. This field is read-only. + /// + public static readonly PathString Empty = new PathString(String.Empty); + + private readonly string _value; + + /// + /// Initalize the path string with a given value. This value must be in unescaped format. Use + /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format. + /// + /// The unescaped path to be assigned to the Value property. + public PathString(string value) + { + if (!String.IsNullOrEmpty(value) && value[0] != '/') + { + throw new ArgumentException(""/*Resources.Exception_PathMustStartWithSlash*/, "value"); + } + _value = value; + } + + /// + /// The unescaped path value + /// + public string Value + { + get { return _value; } + } + + /// + /// True if the path is not empty + /// + public bool HasValue + { + get { return !String.IsNullOrEmpty(_value); } + } + + /// + /// Provides the path string escaped in a way which is correct for combining into the URI representation. + /// + /// The escaped path value + public override string ToString() + { + return ToUriComponent(); + } + + /// + /// Provides the path string escaped in a way which is correct for combining into the URI representation. + /// + /// The escaped path value + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "Purpose of the method is to return a string")] + public string ToUriComponent() + { + // TODO: Measure the cost of this escaping and consider optimizing. + return HasValue ? String.Join("/", _value.Split('/').Select(Uri.EscapeDataString)) : String.Empty; + } + + /// + /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any + /// value that is not a path. + /// + /// The escaped path as it appears in the URI format. + /// The resulting PathString + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Justification = "Requirements not compatible with Uri processing")] + public static PathString FromUriComponent(string uriComponent) + { + // REVIEW: what is the exactly correct thing to do? + return new PathString(Uri.UnescapeDataString(uriComponent)); + } + + /// + /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported. + /// + /// The Uri object + /// The resulting PathString + public static PathString FromUriComponent(Uri uri) + { + if (uri == null) + { + throw new ArgumentNullException("uri"); + } + // REVIEW: what is the exactly correct thing to do? + return new PathString("/" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped)); + } + + public bool StartsWithSegments(PathString other) + { + string value1 = Value ?? String.Empty; + string value2 = other.Value ?? String.Empty; + if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase)) + { + return value1.Length == value2.Length || value1[value2.Length] == '/'; + } + return false; + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Secondary information needed after boolean result obtained")] + public bool StartsWithSegments(PathString other, out PathString remaining) + { + string value1 = Value ?? String.Empty; + string value2 = other.Value ?? String.Empty; + if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase)) + { + if (value1.Length == value2.Length || value1[value2.Length] == '/') + { + remaining = new PathString(value1.Substring(value2.Length)); + return true; + } + } + remaining = Empty; + return false; + } + + /// + /// Adds two PathString instances into a combined PathString value. + /// + /// The combined PathString value + public PathString Add(PathString other) + { + return new PathString(Value + other.Value); + } + + /// + /// Combines a PathString and QueryString into the joined URI formatted string value. + /// + /// The joined URI formatted string value + public string Add(QueryString other) + { + return ToUriComponent() + other.ToUriComponent(); + } + + /// + /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase. + /// + /// The second PathString for comparison. + /// True if both PathString values are equal + public bool Equals(PathString other) + { + return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Compares this PathString value to another value using a specific StringComparison type + /// + /// The second PathString for comparison + /// The StringComparison type to use + /// True if both PathString values are equal + public bool Equals(PathString other, StringComparison comparisonType) + { + return string.Equals(_value, other._value, comparisonType); + } + + /// + /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase. + /// + /// The second PathString for comparison. + /// True if both PathString values are equal + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation. + /// + /// The hash code + public override int GetHashCode() + { + return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0); + } + + /// + /// Operator call through to Equals + /// + /// The left parameter + /// The right parameter + /// True if both PathString values are equal + public static bool operator ==(PathString left, PathString right) + { + return left.Equals(right, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Operator call through to Equals + /// + /// The left parameter + /// The right parameter + /// True if both PathString values are not equal + public static bool operator !=(PathString left, PathString right) + { + return !left.Equals(right, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Operator call through to Add + /// + /// The left parameter + /// The right parameter + /// The PathString combination of both values + public static PathString operator +(PathString left, PathString right) + { + return left.Add(right); + } + + /// + /// Operator call through to Add + /// + /// The left parameter + /// The right parameter + /// The PathString combination of both values + public static string operator +(PathString left, QueryString right) + { + return left.Add(right); + } + } +} diff --git a/src/Microsoft.AspNet.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..906de25b7f --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/Properties/AssemblyInfo.cs @@ -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.Abstractions")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.AspNet.Abstractions")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("f67dab3e-89ef-4d28-a57e-230af874bbe8")] + +// 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("0.1.0")] +[assembly: AssemblyVersion("0.1.0")] +[assembly: AssemblyFileVersion("0.1.0")] diff --git a/src/Microsoft.AspNet.Abstractions/QueryString.cs b/src/Microsoft.AspNet.Abstractions/QueryString.cs new file mode 100644 index 0000000000..e80f5eedcf --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/QueryString.cs @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNet.Abstractions +{ + /// + /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string + /// + public struct QueryString : IEquatable + { + /// + /// Represents the empty query string. This field is read-only. + /// + public static readonly QueryString Empty = new QueryString(String.Empty); + + private readonly string _value; + + /// + /// Initalize the query string with a given value. This value must be in escaped and delimited format without + /// a leading '?' character. + /// + /// The query string to be assigned to the Value property. + public QueryString(string value) + { + _value = value; + } + + /// + /// Initialize a query string with a single given parameter name and value. The value is + /// + /// The unencoded parameter name + /// The unencoded parameter value + public QueryString(string name, string value) + { + _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value); + } + + /// + /// The unescaped query string without the leading '?' character + /// + public string Value + { + get { return _value; } + } + + /// + /// True if the query string is not empty + /// + public bool HasValue + { + get { return !String.IsNullOrWhiteSpace(_value); } + } + + /// + /// Provides the query string escaped in a way which is correct for combining into the URI representation. + /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally + /// dangerous are escaped. + /// + /// The query string value + public override string ToString() + { + return ToUriComponent(); + } + + /// + /// Provides the query string escaped in a way which is correct for combining into the URI representation. + /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially + /// dangerous are escaped. + /// + /// The query string value + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings", Justification = "Purpose of the method is to return a string")] + public string ToUriComponent() + { + // Escape things properly so System.Uri doesn't mis-interpret the data. + return HasValue ? "?" + _value.Replace("#", "%23") : String.Empty; + } + + /// + /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any + /// value that is not a query. + /// + /// The escaped query as it appears in the URI format. + /// The resulting QueryString + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Justification = "Delimiter characters ? and # must be escaped by this method instead of truncating the value")] + public static QueryString FromUriComponent(string uriComponent) + { + if (String.IsNullOrEmpty(uriComponent)) + { + return new QueryString(string.Empty); + } + if (uriComponent[0] != '?') + { + throw new ArgumentException(""/*Resources.Exception_QueryStringMustStartWithDelimiter*/, "uriComponent"); + } + return new QueryString(uriComponent.Substring(1)); + } + + /// + /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported. + /// + /// The Uri object + /// The resulting QueryString + public static QueryString FromUriComponent(Uri uri) + { + if (uri == null) + { + throw new ArgumentNullException("uri"); + } + return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped)); + } + + public bool Equals(QueryString other) + { + return string.Equals(_value, other._value); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + return obj is QueryString && Equals((QueryString)obj); + } + + public override int GetHashCode() + { + return (_value != null ? _value.GetHashCode() : 0); + } + + public static bool operator ==(QueryString left, QueryString right) + { + return left.Equals(right); + } + + public static bool operator !=(QueryString left, QueryString right) + { + return !left.Equals(right); + } + } +} diff --git a/src/Microsoft.AspNet.Abstractions/RequestDelegate.cs b/src/Microsoft.AspNet.Abstractions/RequestDelegate.cs new file mode 100644 index 0000000000..98b48bcf94 --- /dev/null +++ b/src/Microsoft.AspNet.Abstractions/RequestDelegate.cs @@ -0,0 +1,6 @@ +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Abstractions +{ + public delegate Task RequestDelegate(HttpContextBase context); +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.FeatureModel/FeatureContainer.cs b/src/Microsoft.AspNet.FeatureModel/FeatureContainer.cs new file mode 100644 index 0000000000..1b7949658a --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/FeatureContainer.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using Microsoft.AspNet.FeatureModel.Implementation; + +namespace Microsoft.AspNet.FeatureModel +{ + public class FeatureContainer : IFeatureContainer + { + private readonly IFeatureContainer _defaultFeatures; + private readonly IDictionary _featureByFeatureType = new Dictionary(); + private readonly IDictionary _featureTypeByName = new Dictionary(); + private readonly object _containerSync = new Object(); + private int _containerRevision; + + public FeatureContainer() + { + } + + public FeatureContainer(IFeatureContainer defaultFeatures) + { + _defaultFeatures = defaultFeatures; + } + + public virtual object GetFeature(Type type) + { + object feature; + if (_featureByFeatureType.TryGetValue(type, out feature)) + { + return feature; + } + + Type actualType; + if (_featureTypeByName.TryGetValue(type.FullName, out actualType)) + { + if (_featureByFeatureType.TryGetValue(actualType, out feature)) + { + return Converter.Convert(type, actualType, feature); + } + } + + return _defaultFeatures != null ? _defaultFeatures.GetFeature(type) : null; + } + + public virtual object GetDefaultFeature(Type type) + { + return null; + } + + public virtual void SetFeature(Type type, object feature) + { + lock (_containerSync) + { + Type priorFeatureType; + if (_featureTypeByName.TryGetValue(type.FullName, out priorFeatureType)) + { + if (priorFeatureType == type) + { + _featureByFeatureType[type] = feature; + } + else + { + _featureTypeByName[type.FullName] = type; + _featureByFeatureType.Remove(priorFeatureType); + _featureByFeatureType.Add(type, feature); + } + } + else + { + _featureTypeByName.Add(type.FullName, type); + _featureByFeatureType.Add(type, feature); + } + Interlocked.Increment(ref _containerRevision); + } + } + + public virtual int Revision + { + get { return _containerRevision; } + } + + public void Dispose() + { + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.FeatureModel/IFeatureContainer.cs b/src/Microsoft.AspNet.FeatureModel/IFeatureContainer.cs new file mode 100644 index 0000000000..52529983d0 --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/IFeatureContainer.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNet.FeatureModel +{ + public interface IFeatureContainer : IDisposable + { + object GetFeature(Type type); + void SetFeature(Type type, object feature); + //IEnumerable GetFeatureTypes(); + int Revision { get; } + } +} diff --git a/src/Microsoft.AspNet.FeatureModel/Implementation/Converter.cs b/src/Microsoft.AspNet.FeatureModel/Implementation/Converter.cs new file mode 100644 index 0000000000..7f080ab884 --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/Implementation/Converter.cs @@ -0,0 +1,384 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; + +namespace Microsoft.AspNet.FeatureModel.Implementation +{ + public abstract class NonGenericProxyBase + { + public readonly Type WrappedType; + protected NonGenericProxyBase(Type wrappedType) + { + this.WrappedType = wrappedType; + } + public abstract object UnderlyingInstanceAsObject + { + get; + } + } + + public class BaseType : NonGenericProxyBase where T : class + { + protected T instance; + public BaseType(T inst) + : base(typeof(T)) + { + if (inst == null) throw new InvalidOperationException("should never construct proxy over null"); + this.instance = inst; + } + public T UnderlyingInstance + { + get + { + return instance; + } + } + public override object UnderlyingInstanceAsObject + { + get + { + return instance; + } + } + } + + public class Converter + { + public static object Convert(Type outputType, Type inputType, object input) + { + if (inputType == outputType) return input; + + if (!inputType.IsInterface || !outputType.IsInterface) throw new InvalidOperationException("Both types must be interfaces"); + + if (inputType.GetInterfaces().Contains(outputType)) return input; + + if (input == null) return null; + + Type t = EnsureConverter(outputType, inputType); + + return Activator.CreateInstance(t, input); + } + + public static TOut Convert(Type inputType, object input) + where TOut : class + { + return (TOut)Convert(typeof (TOut), inputType, input); + } + + public static TOut Convert(TIn input) + where TIn : class + where TOut : class + { + return Convert(typeof(TIn), input); + } + + public static TOut Convert(object input) + where TOut : class + { + if (input == null) return null; + var interfaceName = typeof(TOut).FullName; + foreach (var inputType in input.GetType().GetInterfaces()) + { + if (inputType.FullName == interfaceName) + { + return Convert(inputType, input); + } + } + return null; + } + + + public static Type EnsureConverter(Type tout, Type tin) + { + CacheResult result; + if (!ConverterTypeCache.TryGetValue(new Tuple(tin, tout), out result)) + { + EnsureCastPossible(tout, tin); + return EnsureConverter(tout, tin); + } + else + { + if (result is ErrorResult) + { + throw new InvalidCastException((result as ErrorResult).error); + } + else if (result is CurrentlyVerifyingResult) + { + throw new InvalidOperationException("Type cannot be obtained in verification phase"); + } + else if (result is TypeBuilderResult) + { + return (result as TypeBuilderResult).result; + } + else if (result is VerificationSucceededResult) + { + return CreateWrapperType(tout, tin, result as VerificationSucceededResult); + } + else + { + throw new InvalidOperationException("Invalid cache state"); + } + } + } + + class CacheResult + { + } + + class TypeBuilderResult : CacheResult + { + internal TypeBuilderResult(Type result) + { + this.result = result; + } + internal readonly Type result; + } + class ErrorResult : CacheResult + { + internal ErrorResult(string error) + { + this.error = error; + } + internal readonly string error; + } + class CurrentlyVerifyingResult : CacheResult + { + } + enum SuccessKind + { + Identity, + SubInterface, + Wrapper, + } + class VerificationSucceededResult : CacheResult + { + internal VerificationSucceededResult(SuccessKind kind) + { + this.kind = kind; + } + internal VerificationSucceededResult(Dictionary mappings) + { + this.kind = SuccessKind.Wrapper; + this.methodMappings = mappings; + } + internal readonly SuccessKind kind; + internal readonly Dictionary methodMappings; + } + + static Dictionary, CacheResult> ConverterTypeCache = new Dictionary, CacheResult>(); + static ConditionalWeakTable ConverterInstanceCache = new ConditionalWeakTable(); + static AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("ProxyHolderAssembly"), AssemblyBuilderAccess.Run); + static ModuleBuilder modb = ab.DefineDynamicModule("Main Module"); + + class EqComparer : IEqualityComparer + { + + bool IEqualityComparer.Equals(ParameterInfo x, ParameterInfo y) + { + return EqualTypes(x.ParameterType, y.ParameterType); + } + + int IEqualityComparer.GetHashCode(ParameterInfo obj) + { + return obj.GetHashCode(); + } + } + + static bool EqualTypes(Type sourceType, Type targetType) + { + return EnsureCastPossible(targetType, sourceType); + } + + + + static MethodInfo FindCorrespondingMethod(Type targetType, Type sourceType, MethodInfo miTarget) + { + MethodInfo[] sms = sourceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where((MethodInfo mi) => mi.Name == miTarget.Name).ToArray(); + if (sms != null && sms.Length != 0) + { + MethodInfo[] sm = null; + try + { + sm = sms.Where((mi) => (mi.GetParameters().SequenceEqual(miTarget.GetParameters(), new EqComparer()))).ToArray(); + } + catch + { + } + if (sm != null && sm.Length != 0) + { + if (sm.Length > 1) return null; + if (EqualTypes(sm[0].ReturnType, miTarget.ReturnType)) + { + return sm[0]; + } + } + } + MethodInfo[] rval = sourceType.GetInterfaces().Select((inheritedItf) => FindCorrespondingMethod(targetType, inheritedItf, miTarget)).ToArray(); + if (rval == null || rval.Length == 0) return null; + if (rval.Length > 1) return null; + return rval[0]; + + } + + + static void AddMethod(Type targetType, Type sourceType, TypeBuilder tb, MethodInfo miTarget, MethodInfo miSource) + { + ParameterInfo[] pisTarget = miTarget.GetParameters(); + ParameterInfo[] pisSource = miSource.GetParameters(); + MethodBuilder metb; + Type[] typesTarget; + if (pisTarget == null || pisTarget.Length == 0) + { + metb = tb.DefineMethod(miTarget.Name, MethodAttributes.Virtual, CallingConventions.HasThis, miTarget.ReturnType, null); + pisTarget = new ParameterInfo[0]; + typesTarget = new Type[0]; + } + else + { + typesTarget = pisTarget.Select((pi) => pi.ParameterType).ToArray(); + Type[][] requiredCustomMods = pisTarget.Select((pi) => pi.GetRequiredCustomModifiers()).ToArray(); + Type[][] optionalCustomMods = pisTarget.Select((pi) => pi.GetOptionalCustomModifiers()).ToArray(); + + metb = tb.DefineMethod(miTarget.Name, MethodAttributes.Virtual, CallingConventions.HasThis, miTarget.ReturnType, null, null, typesTarget, requiredCustomMods, optionalCustomMods); + } + + ILGenerator il = metb.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldfld, tb.BaseType.GetField("instance", BindingFlags.NonPublic | BindingFlags.Instance)); + for (int pi = 0; pi < pisTarget.Length; pi++) + { + il.Emit(OpCodes.Ldarg, pi + 1); + EmitParamConversion(il, typesTarget[pi], pisSource[pi].ParameterType); + } + il.EmitCall(OpCodes.Callvirt, miSource, null); + + EmitParamConversion(il, miSource.ReturnType, miTarget.ReturnType); + il.Emit(OpCodes.Ret); + + tb.DefineMethodOverride(metb, miTarget); + } + + static void EmitParamConversion(ILGenerator il, Type typeOnStack, Type typeRequiredInSignature) + { + if (typeOnStack != typeRequiredInSignature) + { + if (typeOnStack.GetInterfaces().Contains(typeRequiredInSignature)) + { + il.Emit(OpCodes.Castclass, typeRequiredInSignature); + } + else + { + Label lEnd = il.DefineLabel(); + Label lCreateProxy = il.DefineLabel(); + il.Emit(OpCodes.Dup); // o o + il.Emit(OpCodes.Brfalse_S, lEnd); // o + il.Emit(OpCodes.Dup); // o o + il.Emit(OpCodes.Isinst, typeof(NonGenericProxyBase)); // o [p/n] + il.Emit(OpCodes.Brfalse_S, lCreateProxy); // o + il.Emit(OpCodes.Isinst, typeof(NonGenericProxyBase)); // p + il.EmitCall(OpCodes.Callvirt, typeof(NonGenericProxyBase).GetMethod("get_UnderlyingInstanceAsObject"), null); // uo + il.Emit(OpCodes.Dup); // uo uo + il.Emit(OpCodes.Isinst, typeRequiredInSignature); // uo [ro/n] + il.Emit(OpCodes.Brtrue_S, lEnd); // uo + il.MarkLabel(lCreateProxy); // uo + Type paramProxyType = EnsureConverter(typeRequiredInSignature, typeOnStack); + il.Emit(OpCodes.Newobj, paramProxyType.GetConstructors()[0]); + il.MarkLabel(lEnd); // ro + } + } + } + + + + static bool EnsureCastPossible(Type targetType, Type sourceType) + { + var key = new Tuple(sourceType, targetType); + CacheResult cr = null; + if (ConverterTypeCache.TryGetValue(key, out cr)) + { + if (cr is CurrentlyVerifyingResult || cr is VerificationSucceededResult || cr is TypeBuilderResult) return true; + if (cr is ErrorResult) return false; + } + if (targetType == sourceType) + { + ConverterTypeCache[key] = new VerificationSucceededResult(SuccessKind.Identity); + return true; + } + if (targetType.GetInterfaces().Contains(sourceType)) + { + ConverterTypeCache[key] = new VerificationSucceededResult(SuccessKind.SubInterface); + return true; + } + if (!targetType.IsInterface || !sourceType.IsInterface) + { + ConverterTypeCache[key] = new ErrorResult("Cannot cast " + sourceType + " to " + targetType); + return false; + } + bool success = false; + ConverterTypeCache[key] = new CurrentlyVerifyingResult(); + try + { + Dictionary mappings = new Dictionary(); + foreach (MethodInfo mi in targetType.GetMethods().Concat(targetType.GetInterfaces().SelectMany((itf) => itf.GetMethods()))) + { + MethodInfo mapping = FindCorrespondingMethod(targetType, sourceType, mi); + if (mapping == null) + { + ConverterTypeCache[key] = new ErrorResult("Can not cast " + sourceType + " to " + targetType + " because of missing method: " + mi.Name); + return false; + } + mappings[mi] = mapping; + } + ConverterTypeCache[key] = new VerificationSucceededResult(mappings); + success = true; + return true; + } + finally + { + if (!success) + { + if (!(ConverterTypeCache[key] is ErrorResult)) + { + ConverterTypeCache[key] = new ErrorResult("Can not cast " + sourceType + " to " + targetType); + } + } + } + } + + static int counter = 0; + static Type CreateWrapperType(Type targetType, Type sourceType, VerificationSucceededResult result) + { + Dictionary mappings = result.methodMappings; + Type baseType = Assembly.GetExecutingAssembly().GetType("InterfaceMapper.BaseType`1").MakeGenericType(sourceType); + TypeBuilder tb = modb.DefineType("ProxyType" + counter++ + " wrapping:" + sourceType.Name + " to look like:" + targetType.Name, TypeAttributes.Class, baseType, new Type[] { targetType }); + ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { sourceType }); + ILGenerator il = cb.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, sourceType); + il.Emit(OpCodes.Call, baseType.GetConstructor(new Type[] { sourceType })); + il.Emit(OpCodes.Ret); + var tuple = new Tuple(sourceType, targetType); + try + { + ConverterTypeCache[tuple] = new TypeBuilderResult(tb); + foreach (MethodInfo mi in targetType.GetMethods().Concat(targetType.GetInterfaces().SelectMany((itf) => itf.GetMethods()))) + { + AddMethod(targetType, sourceType, tb, mi, mappings[mi]); + } + Type t = tb.CreateType(); + ConverterTypeCache[tuple] = new TypeBuilderResult(t); + return t; + } + catch (Exception e) + { + ConverterTypeCache[tuple] = new ErrorResult(e.Message); + throw; + } + } + + } +} diff --git a/src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.csproj b/src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.csproj new file mode 100644 index 0000000000..a3db9ed3d3 --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.csproj @@ -0,0 +1,54 @@ + + + + + Debug + AnyCPU + {A780873E-09F9-4E44-AE06-AF00C4E88E1E} + Library + Properties + Microsoft.AspNet.FeatureModel + Microsoft.AspNet.FeatureModel + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Microsoft.AspNet.FeatureModel.XML + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.nuspec b/src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.nuspec new file mode 100644 index 0000000000..1b6a2894c7 --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/Microsoft.AspNet.FeatureModel.nuspec @@ -0,0 +1,22 @@ + + + $id$ + $version$ + $authors$ + $authors$ + $licenseUrl$ + $projectUrl$ + true + $title$ + $title$ + $tags$ + + + + + + + + + + diff --git a/src/Microsoft.AspNet.FeatureModel/ObjectFeatureContainer.cs b/src/Microsoft.AspNet.FeatureModel/ObjectFeatureContainer.cs new file mode 100644 index 0000000000..48bcb98b75 --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/ObjectFeatureContainer.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.AspNet.FeatureModel.Implementation; + +namespace Microsoft.AspNet.FeatureModel +{ + public class ObjectFeatureContainer : IFeatureContainer + { + private readonly object _instance; + + public ObjectFeatureContainer(object instance) + { + _instance = instance; + } + + public void Dispose() + { + var disposable = _instance as IDisposable; + if (disposable != null) + { + disposable.Dispose(); + } + } + + public object GetFeature(Type type) + { + if (type.IsInstanceOfType(_instance)) + { + return _instance; + } + foreach (var interfaceType in _instance.GetType().GetInterfaces()) + { + if (interfaceType.FullName == type.FullName) + { + return Converter.Convert(interfaceType, type, _instance); + } + } + return null; + } + + public void SetFeature(Type type, object feature) + { + throw new NotImplementedException(); + } + + public int Revision + { + get { return 0; } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.FeatureModel/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.FeatureModel/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..264c8db996 --- /dev/null +++ b/src/Microsoft.AspNet.FeatureModel/Properties/AssemblyInfo.cs @@ -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.FeatureModel")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.AspNet.FeatureModel")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("cf678d83-e6f7-4433-9bf2-c0efa68e399b")] + +// 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("0.1.0")] +[assembly: AssemblyVersion("0.1.0")] +[assembly: AssemblyFileVersion("0.1.0")] diff --git a/src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentBase.cs b/src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentBase.cs new file mode 100644 index 0000000000..4d1036d835 --- /dev/null +++ b/src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentBase.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNet.FeatureModel; + +namespace Microsoft.AspNet.HttpEnvironment +{ + public abstract class HttpEnvironmentBase : FeatureContainer, IHttpEnvironment + { + } +} diff --git a/src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentExtensions.cs b/src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentExtensions.cs new file mode 100644 index 0000000000..ab296451d5 --- /dev/null +++ b/src/Microsoft.AspNet.HttpEnvironment/HttpEnvironmentExtensions.cs @@ -0,0 +1,10 @@ +namespace Microsoft.AspNet.HttpEnvironment +{ + public static class HttpEnvironmentExtensions + { + public static TFeature GetFeature(this IHttpEnvironment environment) where TFeature : class + { + return (TFeature)environment.GetFeature(typeof(TFeature)); + } + } +} diff --git a/src/Microsoft.AspNet.HttpEnvironment/IHttpEnvironment.cs b/src/Microsoft.AspNet.HttpEnvironment/IHttpEnvironment.cs new file mode 100644 index 0000000000..ab0bb92bc9 --- /dev/null +++ b/src/Microsoft.AspNet.HttpEnvironment/IHttpEnvironment.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNet.FeatureModel; + +namespace Microsoft.AspNet.HttpEnvironment +{ + public interface IHttpEnvironment : IFeatureContainer + { + } +} diff --git a/src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.csproj b/src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.csproj new file mode 100644 index 0000000000..b1db630e6e --- /dev/null +++ b/src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.csproj @@ -0,0 +1,59 @@ + + + + + Debug + AnyCPU + {46D69EC9-7096-49D8-A184-A9BB5B2419A1} + Library + Properties + Microsoft.AspNet.HttpEnvironment + Microsoft.AspNet.HttpEnvironment + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Microsoft.AspNet.HttpEnvironment.XML + + + + + + + + + + + + + {A780873E-09F9-4E44-AE06-AF00C4E88E1E} + Microsoft.AspNet.FeatureModel + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.nuspec b/src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.nuspec new file mode 100644 index 0000000000..1b6a2894c7 --- /dev/null +++ b/src/Microsoft.AspNet.HttpEnvironment/Microsoft.AspNet.HttpEnvironment.nuspec @@ -0,0 +1,22 @@ + + + $id$ + $version$ + $authors$ + $authors$ + $licenseUrl$ + $projectUrl$ + true + $title$ + $title$ + $tags$ + + + + + + + + + + diff --git a/src/Microsoft.AspNet.HttpEnvironment/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.HttpEnvironment/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d68b8666f2 --- /dev/null +++ b/src/Microsoft.AspNet.HttpEnvironment/Properties/AssemblyInfo.cs @@ -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.Environments")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.AspNet.Environments")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("1b326e9f-7c7a-42cd-9861-cdbef8353aed")] + +// 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("0.1.0")] +[assembly: AssemblyVersion("0.1.0")] +[assembly: AssemblyFileVersion("0.1.0")] diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpApplicationInformation.cs b/src/Microsoft.AspNet.HttpFeature/IHttpApplicationInformation.cs new file mode 100644 index 0000000000..497bff550b --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpApplicationInformation.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpApplicationInformation + { + string AppName { get; set; } + string AppMode { get; set; } + CancellationToken OnAppDisposing { get; set; } + } +} diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpBuffering.cs b/src/Microsoft.AspNet.HttpFeature/IHttpBuffering.cs new file mode 100644 index 0000000000..2936208463 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpBuffering.cs @@ -0,0 +1,8 @@ +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpBuffering + { + void DisableRequestBuffering(); + void DisableResponseBuffering(); + } +} diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpConnection.cs b/src/Microsoft.AspNet.HttpFeature/IHttpConnection.cs new file mode 100644 index 0000000000..a375e3358b --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpConnection.cs @@ -0,0 +1,13 @@ +using System.Net; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpConnection + { + IPAddress RemoteIpAddress { get; set; } + int RemotePort { get; set; } + IPAddress LocalIpAddress { get; set; } + int LocalPort { get; set; } + bool IsLocal { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpRequest.cs b/src/Microsoft.AspNet.HttpFeature/IHttpRequest.cs new file mode 100644 index 0000000000..f125863ee2 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpRequest.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpRequest + { + string Protocol { get; set; } + string Scheme { get; set; } + string Method { get; set; } + string PathBase { get; set; } + string Path { get; set; } + string QueryString { get; set; } + IDictionary Headers { get; set; } + Stream Body { get; set; } + Uri Uri { get; } + } +} diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpResponse.cs b/src/Microsoft.AspNet.HttpFeature/IHttpResponse.cs new file mode 100644 index 0000000000..85921559eb --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpResponse.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpResponse + { + int StatusCode { get; set; } + string ReasonPhrase { get; set; } + IDictionary Headers { get; set; } + Stream Body { get; set; } + void OnSendingHeaders(Action callback, object state); + } +} diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpSendFile.cs b/src/Microsoft.AspNet.HttpFeature/IHttpSendFile.cs new file mode 100644 index 0000000000..5d10d36c32 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpSendFile.cs @@ -0,0 +1,10 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpSendFile + { + Task SendFileAsync(string path, long offset, long? length, CancellationToken cancellation); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpTransportLayerSecurity.cs b/src/Microsoft.AspNet.HttpFeature/IHttpTransportLayerSecurity.cs new file mode 100644 index 0000000000..0d4555284e --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpTransportLayerSecurity.cs @@ -0,0 +1,11 @@ +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpTransportLayerSecurity + { + X509Certificate ClientCertificate { get; set; } + Task LoadAsync(); + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpWebSocketAccept.cs b/src/Microsoft.AspNet.HttpFeature/IHttpWebSocketAccept.cs new file mode 100644 index 0000000000..f5dbfb8c21 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/IHttpWebSocketAccept.cs @@ -0,0 +1,11 @@ +using System.Net.WebSockets; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IHttpWebSocketAccept + { + bool IsWebSocketRequest { get; set; } + Task AcceptAsync(); + } +} diff --git a/src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.csproj b/src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.csproj new file mode 100644 index 0000000000..f881a5f0c9 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.csproj @@ -0,0 +1,64 @@ + + + + + Debug + AnyCPU + {42309978-0661-41D8-8654-39453265C5F9} + Library + Properties + Microsoft.AspNet.HttpFeature + Microsoft.AspNet.HttpFeature + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Microsoft.AspNet.HttpFeature.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.nuspec b/src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.nuspec new file mode 100644 index 0000000000..1b6a2894c7 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Microsoft.AspNet.HttpFeature.nuspec @@ -0,0 +1,22 @@ + + + $id$ + $version$ + $authors$ + $authors$ + $licenseUrl$ + $projectUrl$ + true + $title$ + $title$ + $tags$ + + + + + + + + + + diff --git a/src/Microsoft.AspNet.HttpFeature/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.HttpFeature/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..80a1326d0b --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Properties/AssemblyInfo.cs @@ -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.Interfaces")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.AspNet.Interfaces")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("fbcea83c-9fdd-445d-a2d4-93e9062754f3")] + +// 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("0.1.0")] +[assembly: AssemblyVersion("0.1.0")] +[assembly: AssemblyFileVersion("0.1.0")] diff --git a/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationChallenge.cs b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationChallenge.cs new file mode 100644 index 0000000000..cb336ef6c6 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationChallenge.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Microsoft.AspNet.Interfaces +{ + public interface IAuthenticationChallenge + { + IEnumerable AuthenticationTypes { get; } + IDictionary Properties { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationDescription.cs b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationDescription.cs new file mode 100644 index 0000000000..590addffc4 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationDescription.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Microsoft.AspNet.Interfaces.Security +{ + public interface IAuthenticationDescription + { + IDictionary Properties { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationResult.cs b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationResult.cs new file mode 100644 index 0000000000..93c9e9a08d --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationResult.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Security.Claims; + +namespace Microsoft.AspNet.Interfaces.Security +{ + public interface IAuthenticationResult + { + ClaimsIdentity Identity { get; } + IDictionary Properties { get; } + IAuthenticationDescription Description { get; } + } +} diff --git a/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignIn.cs b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignIn.cs new file mode 100644 index 0000000000..663f19a9a3 --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignIn.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Security.Claims; + +namespace Microsoft.AspNet.Interfaces.Security +{ + public interface IAuthenticationSignIn + { + ClaimsPrincipal User { get; } + IDictionary Properties { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignOut.cs b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignOut.cs new file mode 100644 index 0000000000..763bcaed7f --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Security/IAuthenticationSignOut.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Microsoft.AspNet.Interfaces.Security +{ + public interface IAuthenticationSignOut + { + IEnumerable AuthenticationTypes { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.HttpFeature/Security/IHttpAuthentication.cs b/src/Microsoft.AspNet.HttpFeature/Security/IHttpAuthentication.cs new file mode 100644 index 0000000000..ed955970ac --- /dev/null +++ b/src/Microsoft.AspNet.HttpFeature/Security/IHttpAuthentication.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.Security.Principal; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Interfaces.Security +{ + public interface IHttpAuthentication + { + IPrincipal User { get; set; } + + IEnumerable Authenticate(string[] authenticationTypes); + Task> AuthenticateAsync(string[] authenticationTypes); + + IAuthenticationChallenge ChallengeDetails { get; set; } + IAuthenticationSignIn SignInDetails { get; set; } + IAuthenticationSignOut SignOutDetails { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore.Tests/BuilderTests.cs b/src/Microsoft.AspNet.PipelineCore.Tests/BuilderTests.cs new file mode 100644 index 0000000000..d4f89b64c4 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore.Tests/BuilderTests.cs @@ -0,0 +1,24 @@ +using Microsoft.AspNet.Abstractions; +using Shouldly; +using Xunit; + +namespace Microsoft.AspNet.PipelineCore.Tests +{ + public class BuilderTests + { + [Fact] + public void BuildReturnsCallableDelegate() + { + var builder = new Builder(); + var app = builder.Build(); + + var mockHttpContext = new Moq.Mock(); + var mockHttpResponse = new Moq.Mock(); + mockHttpContext.SetupGet(x => x.Response).Returns(mockHttpResponse.Object); + mockHttpResponse.SetupProperty(x => x.StatusCode); + + app.Invoke(mockHttpContext.Object); + mockHttpContext.Object.Response.StatusCode.ShouldBe(404); + } + } +} diff --git a/src/Microsoft.AspNet.PipelineCore.Tests/Microsoft.AspNet.PipelineCore.Tests.csproj b/src/Microsoft.AspNet.PipelineCore.Tests/Microsoft.AspNet.PipelineCore.Tests.csproj new file mode 100644 index 0000000000..143f0ac203 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore.Tests/Microsoft.AspNet.PipelineCore.Tests.csproj @@ -0,0 +1,79 @@ + + + + + Debug + AnyCPU + {86942914-0334-4352-87ED-B971281C74E2} + Library + Properties + Microsoft.AspNet.PipelineCore.Tests + Microsoft.AspNet.PipelineCore.Tests + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Microsoft.AspNet.PipelineCore.Tests.XML + + + + False + ..\..\packages\Moq.4.2.1312.1622\lib\net40\Moq.dll + + + False + ..\..\packages\Shouldly.1.1.1.1\lib\35\Shouldly.dll + + + + + + + + + + False + ..\..\packages\xunit.1.9.2\lib\net20\xunit.dll + + + + + + + + + + + + {A4D3E280-8838-4614-9B99-4874C3CBDF82} + Microsoft.AspNet.PipelineCore + + + {4E1520B1-01F4-481B-96A2-24067EAA52FA} + Microsoft.AspNet.Abstractions + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore.Tests/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.PipelineCore.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..ca7eab6695 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore.Tests/Properties/AssemblyInfo.cs @@ -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.PipelineCore.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.AspNet.PipelineCore.Tests")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("7c564547-b037-4054-a1ec-18e62717be47")] + +// 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("0.1.0")] +[assembly: AssemblyVersion("0.1.0")] +[assembly: AssemblyFileVersion("0.1.0")] diff --git a/src/Microsoft.AspNet.PipelineCore.Tests/packages.config b/src/Microsoft.AspNet.PipelineCore.Tests/packages.config new file mode 100644 index 0000000000..2190a4eebc --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore.Tests/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore/Builder.cs b/src/Microsoft.AspNet.PipelineCore/Builder.cs new file mode 100644 index 0000000000..1e350b305d --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/Builder.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.FeatureModel; +using Microsoft.AspNet.HttpEnvironment; +using Microsoft.AspNet.Interfaces; +using Microsoft.AspNet.PipelineCore.Owin; + +namespace Microsoft.AspNet.PipelineCore +{ + public class Builder : IBuilder + { + private readonly IFeatureContainer _features; + private readonly IList _components = new List(); + + public Builder() + { + _features = new FeatureModel.FeatureContainer(); + } + + public Builder(IFeatureContainer features) + { + _features = features; + } + + public void Dispose() + { + _features.Dispose(); + } + + public virtual object GetFeature(Type type) + { + return _features.GetFeature(type); + } + + public virtual void SetFeature(Type type, object feature) + { + _features.SetFeature(type, feature); + } + + public virtual int Revision + { + get { return _features.Revision; } + } + + public IBuilder Use(object middleware, params object[] args) + { + _components.Add(new Entry(middleware, args)); + return this; + } + + class Entry + { + private readonly object _middleware; + private readonly object[] _args; + + public Entry(object middleware, object[] args) + { + _middleware = middleware; + _args = args; + } + } + + public IBuilder New() + { + return new Builder(_features); + } + + public RequestDelegate Build() + { + RequestDelegate app = async context => context.Response.StatusCode = 404; + + foreach (var component in _components.Reverse()) + { + app = Activate(component, app); + } + + return app; + } + + private RequestDelegate Activate(Entry component, RequestDelegate app) + { + return app; + } + + public Func Adapt(object app) + { + return null; + } + } +} diff --git a/src/Microsoft.AspNet.PipelineCore/HttpContext.cs b/src/Microsoft.AspNet.PipelineCore/HttpContext.cs new file mode 100644 index 0000000000..a75c522b56 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/HttpContext.cs @@ -0,0 +1,44 @@ +using System; +using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.FeatureModel; +using Microsoft.AspNet.HttpEnvironment; + +namespace Microsoft.AspNet.PipelineCore +{ + public class HttpContext : HttpContextBase, IHttpEnvironment + { + private readonly IFeatureContainer _features; + private readonly HttpRequestBase _request; + private readonly HttpResponseBase _response; + + public HttpContext(IHttpEnvironment environment) + { + _features = environment; + _request = new HttpRequest(this); + _response = new HttpResponse(this); + } + + public override HttpRequestBase Request { get { return _request; } } + public override HttpResponseBase Response { get { return _response; } } + + public void Dispose() + { + _features.Dispose(); + } + + public object GetFeature(Type type) + { + return _features.GetFeature(type); + } + + public void SetFeature(Type type, object feature) + { + _features.SetFeature(type, feature); + } + + public int Revision + { + get { return _features.Revision; } + } + } +} diff --git a/src/Microsoft.AspNet.PipelineCore/HttpRequest.cs b/src/Microsoft.AspNet.PipelineCore/HttpRequest.cs new file mode 100644 index 0000000000..2a7385d81a --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/HttpRequest.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.HttpEnvironment; +using Microsoft.AspNet.Interfaces; + +namespace Microsoft.AspNet.PipelineCore +{ + public class HttpRequest : HttpRequestBase + { + private readonly HttpContext _context; + private int _revision; + private IHttpRequest _request; + private IHttpConnection _connection; + + public HttpRequest(HttpContext context) + { + _context = context; + } + + private IHttpRequest IHttpRequest + { + get { return EnsureCurrent(_request) ?? (_request = _context.GetFeature()); } + } + + private IHttpConnection IHttpConnection + { + get { return EnsureCurrent(_connection) ?? (_connection = _context.GetFeature()); } + } + + private T EnsureCurrent(T feature) where T : class + { + if (_revision == _context.Revision) return feature; + + _request = null; + _connection = null; + _revision = _context.Revision; + return null; + } + + public override HttpContextBase HttpContext { get { return _context; } } + + public override Uri Uri + { + get { return IHttpRequest.Uri; } + } + + //public override Uri Uri { get { _request} } + + public override PathString PathBase + { + get { return new PathString(IHttpRequest.PathBase); } + set { IHttpRequest.PathBase = value.Value; } + } + + public override PathString Path + { + get { return new PathString(IHttpRequest.Path); } + set { IHttpRequest.Path = value.Value; } + } + + public override QueryString QueryString + { + get { return new QueryString(IHttpRequest.QueryString); } + set { IHttpRequest.QueryString = value.Value; } + } + + public override Stream Body + { + get { return IHttpRequest.Body; } + set { IHttpRequest.Body = value; } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore/HttpResponse.cs b/src/Microsoft.AspNet.PipelineCore/HttpResponse.cs new file mode 100644 index 0000000000..bb467e8691 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/HttpResponse.cs @@ -0,0 +1,43 @@ +using System.IO; +using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.HttpEnvironment; +using Microsoft.AspNet.Interfaces; + +namespace Microsoft.AspNet.PipelineCore +{ + public class HttpResponse : HttpResponseBase + { + private readonly HttpContext _context; + private IHttpResponse _response; + private int _revision; + + public HttpResponse(HttpContext context) + { + _context = context; + } + + private IHttpResponse IHttpResponse + { + get { return EnsureCurrent(_response) ?? (_response = _context.GetFeature()); } + } + + private T EnsureCurrent(T feature) where T : class + { + if (_revision == _context.Revision) return feature; + + _response = null; + _revision = _context.Revision; + return null; + } + + public override HttpContextBase HttpContext { get { return _context; } } + + public override int StatusCode + { + get { return IHttpResponse.StatusCode; } + set { IHttpResponse.StatusCode = value; } + } + + public override Stream Body { get { return _response.Body; } set { _response.Body = value; } } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.csproj b/src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.csproj new file mode 100644 index 0000000000..1cd72c4c66 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.csproj @@ -0,0 +1,75 @@ + + + + + Debug + AnyCPU + {A4D3E280-8838-4614-9B99-4874C3CBDF82} + Library + Properties + Microsoft.AspNet.PipelineCore + Microsoft.AspNet.PipelineCore + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Microsoft.AspNet.PipelineCore.XML + + + + + + + + + + + + + + + + + {A780873E-09F9-4E44-AE06-AF00C4E88E1E} + Microsoft.AspNet.FeatureModel + + + {4e1520b1-01f4-481b-96a2-24067eaa52fa} + Microsoft.AspNet.Abstractions + + + {46D69EC9-7096-49D8-A184-A9BB5B2419A1} + Microsoft.AspNet.HttpEnvironment + + + {42309978-0661-41d8-8654-39453265c5f9} + Microsoft.AspNet.HttpFeature + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.nuspec b/src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.nuspec new file mode 100644 index 0000000000..1b6a2894c7 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/Microsoft.AspNet.PipelineCore.nuspec @@ -0,0 +1,22 @@ + + + $id$ + $version$ + $authors$ + $authors$ + $licenseUrl$ + $projectUrl$ + true + $title$ + $title$ + $tags$ + + + + + + + + + + diff --git a/src/Microsoft.AspNet.PipelineCore/Owin/OwinConstants.cs b/src/Microsoft.AspNet.PipelineCore/Owin/OwinConstants.cs new file mode 100644 index 0000000000..c7eafe6019 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/Owin/OwinConstants.cs @@ -0,0 +1,174 @@ +namespace Microsoft.AspNet.PipelineCore.Owin +{ + internal static class OwinConstants + { + #region OWIN v1.0.0 - 3.2.1. Request Data + + // http://owin.org/spec/owin-1.0.0.html + + public const string RequestScheme = "owin.RequestScheme"; + public const string RequestMethod = "owin.RequestMethod"; + public const string RequestPathBase = "owin.RequestPathBase"; + public const string RequestPath = "owin.RequestPath"; + public const string RequestQueryString = "owin.RequestQueryString"; + public const string RequestProtocol = "owin.RequestProtocol"; + public const string RequestHeaders = "owin.RequestHeaders"; + public const string RequestBody = "owin.RequestBody"; + + #endregion + + #region OWIN v1.0.0 - 3.2.2. Response Data + + // http://owin.org/spec/owin-1.0.0.html + + public const string ResponseStatusCode = "owin.ResponseStatusCode"; + public const string ResponseReasonPhrase = "owin.ResponseReasonPhrase"; + public const string ResponseProtocol = "owin.ResponseProtocol"; + public const string ResponseHeaders = "owin.ResponseHeaders"; + public const string ResponseBody = "owin.ResponseBody"; + + #endregion + + #region OWIN v1.0.0 - 3.2.3. Other Data + + // http://owin.org/spec/owin-1.0.0.html + + public const string CallCancelled = "owin.CallCancelled"; + + public const string OwinVersion = "owin.Version"; + + #endregion + + #region OWIN Keys for IAppBuilder.Properties + + internal static class Builder + { + public const string AddSignatureConversion = "builder.AddSignatureConversion"; + public const string DefaultApp = "builder.DefaultApp"; + } + + #endregion + + #region OWIN Key Guidelines and Common Keys - 6. Common keys + + // http://owin.org/spec/CommonKeys.html + + internal static class CommonKeys + { + public const string ClientCertificate = "ssl.ClientCertificate"; + public const string RemoteIpAddress = "server.RemoteIpAddress"; + public const string RemotePort = "server.RemotePort"; + public const string LocalIpAddress = "server.LocalIpAddress"; + public const string LocalPort = "server.LocalPort"; + public const string IsLocal = "server.IsLocal"; + public const string TraceOutput = "host.TraceOutput"; + public const string Addresses = "host.Addresses"; + public const string AppName = "host.AppName"; + public const string Capabilities = "server.Capabilities"; + public const string OnSendingHeaders = "server.OnSendingHeaders"; + public const string OnAppDisposing = "host.OnAppDisposing"; + public const string Scheme = "scheme"; + public const string Host = "host"; + public const string Port = "port"; + public const string Path = "path"; + } + + #endregion + + #region SendFiles v0.3.0 + + // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm + + internal static class SendFiles + { + // 3.1. Startup + + public const string Version = "sendfile.Version"; + public const string Support = "sendfile.Support"; + public const string Concurrency = "sendfile.Concurrency"; + + // 3.2. Per Request + + public const string SendAsync = "sendfile.SendAsync"; + } + + #endregion + + #region Opaque v0.3.0 + + // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm + + internal static class OpaqueConstants + { + // 3.1. Startup + + public const string Version = "opaque.Version"; + + // 3.2. Per Request + + public const string Upgrade = "opaque.Upgrade"; + + // 5. Consumption + + public const string Stream = "opaque.Stream"; + // public const string Version = "opaque.Version"; // redundant, declared above + public const string CallCancelled = "opaque.CallCancelled"; + } + + #endregion + + #region WebSocket v0.4.0 + + // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm + + internal static class WebSocket + { + // 3.1. Startup + + public const string Version = "websocket.Version"; + + // 3.2. Per Request + + public const string Accept = "websocket.Accept"; + + // 4. Accept + + public const string SubProtocol = "websocket.SubProtocol"; + + // 5. Consumption + + public const string SendAsync = "websocket.SendAsync"; + public const string ReceiveAsync = "websocket.ReceiveAsync"; + public const string CloseAsync = "websocket.CloseAsync"; + // public const string Version = "websocket.Version"; // redundant, declared above + public const string CallCancelled = "websocket.CallCancelled"; + public const string ClientCloseStatus = "websocket.ClientCloseStatus"; + public const string ClientCloseDescription = "websocket.ClientCloseDescription"; + } + + #endregion + + #region Security v0.1.0 + + // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm + + internal static class Security + { + // 3.2. Per Request + + public const string User = "server.User"; + + public const string Authenticate = "security.Authenticate"; + + // 3.3. Response + + public const string SignIn = "security.SignIn"; + + public const string SignOut = "security.SignOut"; + + public const string Challenge = "security.Challenge"; + } + + #endregion + } +} diff --git a/src/Microsoft.AspNet.PipelineCore/Owin/OwinHttpEnvironment.cs b/src/Microsoft.AspNet.PipelineCore/Owin/OwinHttpEnvironment.cs new file mode 100644 index 0000000000..8f8a948434 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/Owin/OwinHttpEnvironment.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNet.HttpEnvironment; +using Microsoft.AspNet.Interfaces; + +namespace Microsoft.AspNet.PipelineCore.Owin +{ + public class OwinHttpEnvironment : + IHttpRequest, IHttpResponse, IHttpConnection, IHttpSendFile, IHttpTransportLayerSecurity + { + public IDictionary Environment { get; set; } + + public OwinHttpEnvironment(IDictionary environment) + { + Environment = environment; + } + + T Prop(string key) + { + object value; + if (Environment.TryGetValue(key, out value) && value is T) + { + return (T)value; + } + return default(T); + } + + void Prop(string key, object value) + { + Environment[key] = value; + } + + string IHttpRequest.Protocol + { + get { return Prop("owin.RequestProtocol"); } + set { Prop("owin.RequestProtocol", value); } + } + + Uri IHttpRequest.Uri + { + get { throw new NotImplementedException(); } + } + + string IHttpRequest.Scheme + { + get { return Prop("owin.RequestScheme"); } + set { Prop("owin.RequestScheme", value); } + } + + string IHttpRequest.Method + { + get { return Prop("owin.RequestMethod"); } + set { Prop("owin.RequestMethod", value); } + } + + string IHttpRequest.PathBase + { + get { return Prop("owin.RequestPathBase"); } + set { Prop("owin.RequestPathBase", value); } + } + + string IHttpRequest.Path + { + get { return Prop("owin.RequestPath"); } + set { Prop("owin.RequestPath", value); } + } + + string IHttpRequest.QueryString + { + get { return Prop("owin.RequestQueryString"); } + set { Prop("owin.RequestQueryString", value); } + } + + IDictionary IHttpRequest.Headers + { + get { return Prop>("owin.RequestHeaders"); } + set { Prop("owin.RequestHeaders", value); } + } + + Stream IHttpRequest.Body + { + get { return Prop("owin.RequestBody"); } + set { Prop("owin.RequestBody", value); } + } + + int IHttpResponse.StatusCode + { + get { return Prop("owin.ResponseStatusCode"); } + set { Prop("owin.ResponseStatusCode", value); } + } + + string IHttpResponse.ReasonPhrase + { + get { return Prop("owin.ResponseReasonPhrase"); } + set { Prop("owin.ResponseReasonPhrase", value); } + } + + IDictionary IHttpResponse.Headers + { + get { return Prop>("owin.ResponseHeaders"); } + set { Prop("owin.ResponseHeaders", value); } + } + + Stream IHttpResponse.Body + { + get { return Prop("owin.ResponseBody"); } + set { Prop("owin.ResponseBody", value); } + } + + void IHttpResponse.OnSendingHeaders(Action callback, object state) + { + // TODO: + } + + IPAddress IHttpConnection.RemoteIpAddress + { + get { return IPAddress.Parse(Prop(OwinConstants.CommonKeys.RemoteIpAddress)); } + set { Prop(OwinConstants.CommonKeys.RemoteIpAddress, value.ToString()); } + } + + int IHttpConnection.RemotePort + { + get { return int.Parse(Prop(OwinConstants.CommonKeys.RemotePort)); } + set { Prop(OwinConstants.CommonKeys.RemotePort, value.ToString(CultureInfo.InvariantCulture)); } + } + + IPAddress IHttpConnection.LocalIpAddress + { + get { return IPAddress.Parse(Prop(OwinConstants.CommonKeys.LocalIpAddress)); } + set { Prop(OwinConstants.CommonKeys.LocalIpAddress, value.ToString()); } + } + + int IHttpConnection.LocalPort + { + get { return int.Parse(Prop(OwinConstants.CommonKeys.LocalPort)); } + set { Prop(OwinConstants.CommonKeys.LocalPort, value.ToString(CultureInfo.InvariantCulture)); } + } + + bool IHttpConnection.IsLocal + { + get { return Prop(OwinConstants.CommonKeys.IsLocal); } + set { Prop(OwinConstants.CommonKeys.LocalPort, value); } + } + + Task IHttpSendFile.SendFileAsync(string path, long offset, long? length, CancellationToken cancellation) + { + throw new NotImplementedException(); + } + + X509Certificate IHttpTransportLayerSecurity.ClientCertificate + { + get { return Prop(OwinConstants.CommonKeys.ClientCertificate); } + set { Prop(OwinConstants.CommonKeys.ClientCertificate, value); } + } + + Task IHttpTransportLayerSecurity.LoadAsync() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.PipelineCore/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.PipelineCore/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..05cb3146e3 --- /dev/null +++ b/src/Microsoft.AspNet.PipelineCore/Properties/AssemblyInfo.cs @@ -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.Abstractions.Implementation")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.AspNet.Abstractions.Implementation")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("5886f89f-de4d-4e44-81c2-7a32b2c89cfd")] + +// 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("0.1.0")] +[assembly: AssemblyVersion("0.1.0")] +[assembly: AssemblyFileVersion("0.1.0")]