diff --git a/CloudEvents.sln b/CloudEvents.sln
index 1d9d4fc..c60967c 100644
--- a/CloudEvents.sln
+++ b/CloudEvents.sln
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudNative.CloudEvents.Amq
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudNative.CloudEvents.Kafka", "src\CloudNative.CloudEvents.Kafka\CloudNative.CloudEvents.Kafka.csproj", "{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CloudNative.CloudEvents.AspNetCore", "src\CloudNative.CloudEvents.AspNetCore\CloudNative.CloudEvents.AspNetCore.csproj", "{C726DD78-2D56-48D3-928A-D10226E3750B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -93,6 +95,7 @@ Global
{39EF4DB0-9890-4CAD-A36E-F7E25D2E72EF}.Release|x64.Build.0 = Release|Any CPU
{39EF4DB0-9890-4CAD-A36E-F7E25D2E72EF}.Release|x86.ActiveCfg = Release|Any CPU
{39EF4DB0-9890-4CAD-A36E-F7E25D2E72EF}.Release|x86.Build.0 = Release|Any CPU
+<<<<<<< HEAD
{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -105,6 +108,20 @@ Global
{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}.Release|x64.Build.0 = Release|Any CPU
{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}.Release|x86.ActiveCfg = Release|Any CPU
{193D6D9D-C1A0-459E-86CF-F207CDF0FC73}.Release|x86.Build.0 = Release|Any CPU
+=======
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Debug|x64.Build.0 = Debug|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Debug|x86.Build.0 = Debug|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Release|x64.ActiveCfg = Release|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Release|x64.Build.0 = Release|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Release|x86.ActiveCfg = Release|Any CPU
+ {C726DD78-2D56-48D3-928A-D10226E3750B}.Release|x86.Build.0 = Release|Any CPU
+>>>>>>> dde2c54... add support for parsing ASP.NET Core HTTP requests into CloudEvents
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/CloudEvents.v3.ncrunchsolution b/CloudEvents.v3.ncrunchsolution
new file mode 100644
index 0000000..f774ab9
--- /dev/null
+++ b/CloudEvents.v3.ncrunchsolution
@@ -0,0 +1,6 @@
+
+
+ False
+ True
+
+
\ No newline at end of file
diff --git a/src/CloudNative.CloudEvents.AspNetCore/CloudNative.CloudEvents.AspNetCore.csproj b/src/CloudNative.CloudEvents.AspNetCore/CloudNative.CloudEvents.AspNetCore.csproj
new file mode 100644
index 0000000..3aa0ce2
--- /dev/null
+++ b/src/CloudNative.CloudEvents.AspNetCore/CloudNative.CloudEvents.AspNetCore.csproj
@@ -0,0 +1,15 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CloudNative.CloudEvents.AspNetCore/HttpRequestExtension.cs b/src/CloudNative.CloudEvents.AspNetCore/HttpRequestExtension.cs
new file mode 100644
index 0000000..8647078
--- /dev/null
+++ b/src/CloudNative.CloudEvents.AspNetCore/HttpRequestExtension.cs
@@ -0,0 +1,120 @@
+// Copyright (c) Cloud Native Foundation.
+// Licensed under the Apache 2.0 license.
+// See LICENSE file in the project root for full license information.
+
+namespace CloudNative.CloudEvents
+{
+ using Microsoft.AspNetCore.Http;
+ using Microsoft.Extensions.Primitives;
+ using Newtonsoft.Json;
+ using System;
+ using System.Net.Mime;
+
+ public static class HttpRequestExtension
+ {
+ const string HttpHeaderPrefix = "ce-";
+
+ const string SpecVersionHttpHeader1 = HttpHeaderPrefix + "cloudEventsVersion";
+
+ const string SpecVersionHttpHeader2 = HttpHeaderPrefix + "specversion";
+
+ static JsonEventFormatter jsonFormatter = new JsonEventFormatter();
+
+ ///
+ /// Converts this HTTP request into a CloudEvent object, with the given extensions.
+ ///
+ /// HTTP request
+ /// List of extension instances
+ /// A CloudEvent instance or 'null' if the request message doesn't hold a CloudEvent
+ public static CloudEvent ToCloudEvent(this HttpRequest httpRequest,
+ params ICloudEventExtension[] extensions)
+ {
+ return ToCloudEvent(httpRequest, null, extensions);
+ }
+
+ ///
+ /// Converts this HTTP request into a CloudEvent object, with the given extensions,
+ /// overriding the formatter.
+ ///
+ /// HTTP request
+ ///
+ /// List of extension instances
+ /// A CloudEvent instance or 'null' if the request message doesn't hold a CloudEvent
+ public static CloudEvent ToCloudEvent(this HttpRequest httpRequest,
+ ICloudEventFormatter formatter = null,
+ params ICloudEventExtension[] extensions)
+ {
+ if (httpRequest.ContentType != null &&
+ httpRequest.ContentType.StartsWith(CloudEvent.MediaType,
+ StringComparison.InvariantCultureIgnoreCase))
+ {
+ // handle structured mode
+ if (formatter == null)
+ {
+ // if we didn't get a formatter, pick one
+ if (httpRequest.ContentType.EndsWith(JsonEventFormatter.MediaTypeSuffix,
+ StringComparison.InvariantCultureIgnoreCase))
+ {
+ formatter = jsonFormatter;
+ }
+ else
+ {
+ throw new InvalidOperationException("Unsupported CloudEvents encoding");
+ }
+ }
+
+ return formatter.DecodeStructuredEvent(httpRequest.Body, extensions);
+ }
+ else
+ {
+ CloudEventsSpecVersion version = CloudEventsSpecVersion.Default;
+ if (httpRequest.Headers[SpecVersionHttpHeader1] != StringValues.Empty)
+ {
+ version = CloudEventsSpecVersion.V0_1;
+ }
+
+ if (httpRequest.Headers[SpecVersionHttpHeader2] != StringValues.Empty)
+ {
+ version = httpRequest.Headers[SpecVersionHttpHeader2] == "0.2"
+ ? CloudEventsSpecVersion.V0_2
+ : CloudEventsSpecVersion.Default;
+ }
+
+ var cloudEvent = new CloudEvent(version, extensions);
+ var attributes = cloudEvent.GetAttributes();
+ foreach (var httpRequestHeader in httpRequest.Headers.Keys)
+ {
+ if (httpRequestHeader.Equals(SpecVersionHttpHeader1,
+ StringComparison.InvariantCultureIgnoreCase) ||
+ httpRequestHeader.Equals(SpecVersionHttpHeader2, StringComparison.InvariantCultureIgnoreCase))
+ {
+ continue;
+ }
+
+ if (httpRequestHeader.StartsWith(HttpHeaderPrefix, StringComparison.InvariantCultureIgnoreCase))
+ {
+ string headerValue = httpRequest.Headers[httpRequestHeader];
+ if (headerValue.StartsWith("{") && headerValue.EndsWith("}") ||
+ headerValue.StartsWith("[") && headerValue.EndsWith("]"))
+ {
+ attributes[httpRequestHeader.Substring(3)] =
+ JsonConvert.DeserializeObject(headerValue);
+ }
+ else
+ {
+ attributes[httpRequestHeader.Substring(3)] = headerValue;
+ attributes[httpRequestHeader.Substring(3)] = headerValue;
+ }
+ }
+ }
+
+ cloudEvent.ContentType = httpRequest.ContentType != null
+ ? new ContentType(httpRequest.ContentType)
+ : null;
+ cloudEvent.Data = httpRequest.Body;
+ return cloudEvent;
+ }
+ }
+
+ }
+}