diff --git a/WebApiContrib.Core.sln b/WebApiContrib.Core.sln
index bc3f645..34a350b 100644
--- a/WebApiContrib.Core.sln
+++ b/WebApiContrib.Core.sln
@@ -1,6 +1,6 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2003
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29926.136
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "01. Core", "01. Core", "{5898776F-DBF8-4C30-85A3-66401B12016F}"
 EndProject
@@ -44,7 +44,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiContrib.Core.Formatte
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiContrib.Core.Yaml.Tests", "tests\WebApiContrib.Core.Yaml.Tests\WebApiContrib.Core.Yaml.Tests.csproj", "{3EC99E77-9F1E-4D43-B70B-E67C61D7E8DB}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApiContrib.Core.Tests", "tests\WebApiContrib.Core.Tests\WebApiContrib.Core.Tests.csproj", "{6466DD2D-6358-4D7F-8562-2517F7F53E3F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiContrib.Core.Tests", "tests\WebApiContrib.Core.Tests\WebApiContrib.Core.Tests.csproj", "{6466DD2D-6358-4D7F-8562-2517F7F53E3F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiContrib.Core.Csv.Tests", "tests\WebApiContrib.Core.Csv.Tests\WebApiContrib.Core.Csv.Tests.csproj", "{202BC540-B2CA-4CCA-8E9C-EE18B0B59A20}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -124,6 +126,10 @@ Global
 		{6466DD2D-6358-4D7F-8562-2517F7F53E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{6466DD2D-6358-4D7F-8562-2517F7F53E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6466DD2D-6358-4D7F-8562-2517F7F53E3F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{202BC540-B2CA-4CCA-8E9C-EE18B0B59A20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{202BC540-B2CA-4CCA-8E9C-EE18B0B59A20}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{202BC540-B2CA-4CCA-8E9C-EE18B0B59A20}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{202BC540-B2CA-4CCA-8E9C-EE18B0B59A20}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -148,6 +154,7 @@ Global
 		{D542971E-D9D3-4E8F-A4BF-D1638D7C2613} = {5898776F-DBF8-4C30-85A3-66401B12016F}
 		{3EC99E77-9F1E-4D43-B70B-E67C61D7E8DB} = {A7A8D928-30D6-4497-8B7D-F233B79A2917}
 		{6466DD2D-6358-4D7F-8562-2517F7F53E3F} = {A7A8D928-30D6-4497-8B7D-F233B79A2917}
+		{202BC540-B2CA-4CCA-8E9C-EE18B0B59A20} = {A7A8D928-30D6-4497-8B7D-F233B79A2917}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {C1758983-E7A8-4669-9176-F46E7A08E588}
diff --git a/tests/WebApiContrib.Core.Csv.Tests/Book.cs b/tests/WebApiContrib.Core.Csv.Tests/Book.cs
new file mode 100644
index 0000000..83caefb
--- /dev/null
+++ b/tests/WebApiContrib.Core.Csv.Tests/Book.cs
@@ -0,0 +1,15 @@
+namespace WebApiContrib.Core.Csv.Tests
+{
+    public class Book
+    {
+        public static Book[] Data = new[]
+            {
+                new Book { Title = "Our Mathematical Universe: My Quest for the Ultimate Nature of Reality", Author = "Max Tegmark"},
+                new Book { Title = "Hockey Towns", Author = "Ron MacLean"},
+            };
+
+        public string Title { get; set; }
+
+        public string Author { get; set; }
+    }
+}
diff --git a/tests/WebApiContrib.Core.Csv.Tests/BooksController.cs b/tests/WebApiContrib.Core.Csv.Tests/BooksController.cs
new file mode 100644
index 0000000..b640a49
--- /dev/null
+++ b/tests/WebApiContrib.Core.Csv.Tests/BooksController.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Mvc;
+
+namespace WebApiContrib.Core.Csv.Tests
+{
+    [Route("api/books")]
+    public class BooksController : ControllerBase
+    {
+        [HttpGet]
+        public IActionResult Get()
+        {
+            return Ok(Book.Data);
+        }
+
+        [HttpGet("{id}")]
+        public IActionResult Get(int id)
+        {
+            if (Book.Data.Length >= id && id > 0)
+            {
+                return Ok(Book.Data[id-1]);
+            }
+
+            return Ok(null);
+        }
+
+        [HttpPost]
+        public IActionResult Post([FromBody]Book book)
+        {
+            return Ok(book);
+        }
+    }
+}
diff --git a/tests/WebApiContrib.Core.Csv.Tests/CsvTests.cs b/tests/WebApiContrib.Core.Csv.Tests/CsvTests.cs
new file mode 100644
index 0000000..a158b66
--- /dev/null
+++ b/tests/WebApiContrib.Core.Csv.Tests/CsvTests.cs
@@ -0,0 +1,141 @@
+using CsvHelper;
+using CsvHelper.Configuration;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.TestHost;
+using Newtonsoft.Json;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace WebApiContrib.Core.Csv.Tests
+{
+    // note: the JSON tests are here to verify that the two formatters do not conflict with each other
+    public class CsvTests
+    {
+        private TestServer _server;
+        public CsvTests()
+        {
+            _server = new TestServer(new WebHostBuilder()
+                    .UseContentRoot(Directory.GetCurrentDirectory())
+                    .UseStartup<Startup>());
+        }
+
+        [Fact]
+        public async Task GetCollection_Text_Csv_Header()
+        {
+            var client = _server.CreateClient();
+
+            var request = new HttpRequestMessage(HttpMethod.Get, "/api/books");
+            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/Csv"));
+            var result = await client.SendAsync(request);
+            var books = Deserialize<Book>(new StreamReader(await result.Content.ReadAsStreamAsync()));
+
+            Assert.Equal(2, books.Length);
+            Assert.Equal(Book.Data[0].Author, books[0].Author);
+            Assert.Equal(Book.Data[0].Title, books[0].Title);
+            Assert.Equal(Book.Data[1].Author, books[1].Author);
+            Assert.Equal(Book.Data[1].Title, books[1].Title);
+        }
+
+        [Fact(Skip = "Returns json instead of csv")]
+        public async Task GetById_Text_Csv_Header()
+        {
+            var client = _server.CreateClient();
+
+            var request = new HttpRequestMessage(HttpMethod.Get, "/api/books/1");
+            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/Csv"));
+            var result = await client.SendAsync(request);
+            var book = Deserialize<Book>(new StreamReader(await result.Content.ReadAsStreamAsync())).Single();
+
+            Assert.NotNull(book);
+            Assert.Equal(Book.Data[0].Author, book.Author);
+            Assert.Equal(Book.Data[0].Title, book.Title);
+        }
+
+        [Fact(Skip = "Returns json instead of csv")]
+        public async Task Post_Text_Csv_Header()
+        {
+            var client = _server.CreateClient();
+
+            var request = new HttpRequestMessage(HttpMethod.Post, "/api/books");
+            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/Csv"));
+
+            var book = new Book
+            {
+                Author = "Tim Parks",
+                Title = "Italian Ways: On and off the Rails from Milan to Palermo"
+            };
+
+            MemoryStream stream = new MemoryStream();
+            StreamWriter writer = new StreamWriter(stream);
+            Serialize(writer,new[] { book });
+            writer.Flush();
+
+            HttpContent data = new StreamContent(stream);
+            data.Headers.ContentType = new MediaTypeHeaderValue("text/Csv");
+
+            request.Content = data;
+            var result = await client.SendAsync(request);
+
+            var echo = Deserialize<Book>(new StreamReader(await result.Content.ReadAsStreamAsync())).Single();
+
+            Assert.NotNull(book);
+            Assert.Equal(book.Author, echo.Author);
+            Assert.Equal(book.Title, echo.Title);
+        }
+
+        [Fact]
+        public async Task GetCollection_JSON_Header()
+        {
+            var client = _server.CreateClient();
+
+            var request = new HttpRequestMessage(HttpMethod.Get, "/api/books");
+            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+            var result = await client.SendAsync(request);
+            var books = JsonConvert.DeserializeObject<Book[]>(await result.Content.ReadAsStringAsync());
+
+            Assert.Equal(2, books.Length);
+            Assert.Equal(Book.Data[0].Author, books[0].Author);
+            Assert.Equal(Book.Data[0].Title, books[0].Title);
+            Assert.Equal(Book.Data[1].Author, books[1].Author);
+            Assert.Equal(Book.Data[1].Title, books[1].Title);
+        }
+
+        private static T[] Deserialize<T>(StreamReader reader)
+        {
+            using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
+            {
+                csv.Configuration.Delimiter = ";";
+                csv.Configuration.RegisterClassMap<BookMap>();
+                return csv.GetRecords<T>().ToArray();
+            }
+        }
+
+        private static void Serialize<T>(StreamWriter writer, IEnumerable<T> obj)
+        {
+            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture, leaveOpen: true))
+            {
+                csv.Configuration.RegisterClassMap<BookMap>();
+
+                csv.WriteRecords(obj);
+            }
+        }
+
+        private class BookMap : ClassMap<Book>
+        {
+            public BookMap()
+            {
+                Map(m => m.Title)
+                    .Index(0);
+                Map(m => m.Author)
+                    .Index(1);
+            }
+        }
+    }
+}
diff --git a/tests/WebApiContrib.Core.Csv.Tests/Startup.cs b/tests/WebApiContrib.Core.Csv.Tests/Startup.cs
new file mode 100644
index 0000000..ecfeb5f
--- /dev/null
+++ b/tests/WebApiContrib.Core.Csv.Tests/Startup.cs
@@ -0,0 +1,35 @@
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using WebApiContrib.Core.Formatter.Csv;
+using WebApiContrib.Core.Formatter.Csv;
+
+namespace WebApiContrib.Core.Csv.Tests
+{
+    public class Startup
+    {
+        public IConfigurationRoot Configuration { get; }
+
+        public Startup(IHostingEnvironment env)
+        {
+            var builder = new ConfigurationBuilder()
+                .SetBasePath(env.ContentRootPath)
+                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+                .AddEnvironmentVariables();
+            Configuration = builder.Build();
+        }
+
+        public void ConfigureServices(IServiceCollection services)
+        {
+            services.AddMvcCore()
+                .AddJsonFormatters()
+                .AddCsvSerializerFormatters();
+        }
+
+        public void Configure(IApplicationBuilder app)
+        {
+            app.UseMvc();
+        }
+    }
+}
diff --git a/tests/WebApiContrib.Core.Csv.Tests/WebApiContrib.Core.Csv.Tests.csproj b/tests/WebApiContrib.Core.Csv.Tests/WebApiContrib.Core.Csv.Tests.csproj
new file mode 100644
index 0000000..9487b98
--- /dev/null
+++ b/tests/WebApiContrib.Core.Csv.Tests/WebApiContrib.Core.Csv.Tests.csproj
@@ -0,0 +1,29 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="CsvHelper" Version="15.0.3" />
+    <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.6" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="2.1.3" />
+    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
+    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+    </PackageReference>
+    <PackageReference Include="AppVeyor.TestLogger" Version="2.0.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\WebApiContrib.Core.Formatter.Csv\WebApiContrib.Core.Formatter.Csv.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file