Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 1d18b33

Browse files
committed
#361 Introduce StringValues to replace string[] usage.
1 parent 6ba7793 commit 1d18b33

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1001
-390
lines changed

HttpAbstractions.sln

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 14
4-
VisualStudioVersion = 14.0.22823.1
4+
VisualStudioVersion = 14.0.23107.0
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5A15F1C-885A-452A-A731-B0173DDBD913}"
77
EndProject
@@ -43,6 +43,14 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Framework.WebEnco
4343
EndProject
4444
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Html.Abstractions", "src\Microsoft.AspNet.Html.Abstractions\Microsoft.AspNet.Html.Abstractions.xproj", "{68A28E4A-3ADE-4187-9625-4FF185887CB3}"
4545
EndProject
46+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{982F09D8-621E-4872-BA7B-BBDEA47D1EFD}"
47+
EndProject
48+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "SampleApp", "samples\SampleApp\SampleApp.xproj", "{1D0764B4-1DEB-4232-A714-D4B7E846918A}"
49+
EndProject
50+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Primitives", "src\Microsoft.AspNet.Primitives\Microsoft.AspNet.Primitives.xproj", "{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}"
51+
EndProject
52+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Primitives.Tests", "test\Microsoft.AspNet.Primitives.Tests\Microsoft.AspNet.Primitives.Tests.xproj", "{61F72E92-B3AE-4A10-B838-44F80AED40AE}"
53+
EndProject
4654
Global
4755
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4856
Debug|Any CPU = Debug|Any CPU
@@ -245,6 +253,42 @@ Global
245253
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
246254
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.ActiveCfg = Release|Any CPU
247255
{68A28E4A-3ADE-4187-9625-4FF185887CB3}.Release|x86.Build.0 = Release|Any CPU
256+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
257+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Any CPU.Build.0 = Debug|Any CPU
258+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
259+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
260+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|x86.ActiveCfg = Debug|Any CPU
261+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Debug|x86.Build.0 = Debug|Any CPU
262+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|Any CPU.ActiveCfg = Release|Any CPU
263+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|Any CPU.Build.0 = Release|Any CPU
264+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
265+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
266+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|x86.ActiveCfg = Release|Any CPU
267+
{1D0764B4-1DEB-4232-A714-D4B7E846918A}.Release|x86.Build.0 = Release|Any CPU
268+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
269+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
270+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
271+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
272+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Debug|x86.ActiveCfg = Debug|Any CPU
273+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Debug|x86.Build.0 = Debug|Any CPU
274+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
275+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Release|Any CPU.Build.0 = Release|Any CPU
276+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
277+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
278+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Release|x86.ActiveCfg = Release|Any CPU
279+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A}.Release|x86.Build.0 = Release|Any CPU
280+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
281+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
282+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
283+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
284+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Debug|x86.ActiveCfg = Debug|Any CPU
285+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Debug|x86.Build.0 = Debug|Any CPU
286+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
287+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Release|Any CPU.Build.0 = Release|Any CPU
288+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
289+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
290+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Release|x86.ActiveCfg = Release|Any CPU
291+
{61F72E92-B3AE-4A10-B838-44F80AED40AE}.Release|x86.Build.0 = Release|Any CPU
248292
EndGlobalSection
249293
GlobalSection(SolutionProperties) = preSolution
250294
HideSolutionNode = FALSE
@@ -268,5 +312,8 @@ Global
268312
{7AE2731D-43CD-4CF8-850A-4914DE2CE930} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21}
269313
{BE9112CB-D87D-4080-9CC3-24492D49CBE6} = {A5A15F1C-885A-452A-A731-B0173DDBD913}
270314
{68A28E4A-3ADE-4187-9625-4FF185887CB3} = {A5A15F1C-885A-452A-A731-B0173DDBD913}
315+
{1D0764B4-1DEB-4232-A714-D4B7E846918A} = {982F09D8-621E-4872-BA7B-BBDEA47D1EFD}
316+
{E5FACCD4-6327-43AA-80A9-AE6F4A3BFE6A} = {A5A15F1C-885A-452A-A731-B0173DDBD913}
317+
{61F72E92-B3AE-4A10-B838-44F80AED40AE} = {F31FF137-390C-49BF-A3BD-7C6ED3597C21}
271318
EndGlobalSection
272319
EndGlobal

samples/SampleApp/Program.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
using System.Diagnostics;
3+
using Microsoft.AspNet.Primitives;
4+
5+
namespace SampleApp
6+
{
7+
public class Program
8+
{
9+
public void Main(string[] args)
10+
{
11+
for (int i = 0; i < 10; i++)
12+
{
13+
Stopwatch timer = new Stopwatch();
14+
timer.Start();
15+
string myString;
16+
string[] myArray;
17+
StringValues myValues;
18+
for (int j = 0; j < 100000000; j++)
19+
{
20+
myString = new string('a', 40);
21+
myArray = new[] { myString };
22+
// myValues = new StringValues(myString);
23+
myValues = new StringValues(myArray);
24+
}
25+
timer.Stop();
26+
Console.WriteLine(timer.Elapsed + ", " + Environment.WorkingSet);
27+
}
28+
}
29+
}
30+
}

samples/SampleApp/SampleApp.xproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
5+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
6+
</PropertyGroup>
7+
8+
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
9+
<PropertyGroup Label="Globals">
10+
<ProjectGuid>1d0764b4-1deb-4232-a714-d4b7e846918a</ProjectGuid>
11+
<RootNamespace>SampleApp</RootNamespace>
12+
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
13+
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
14+
</PropertyGroup>
15+
16+
<PropertyGroup>
17+
<SchemaVersion>2.0</SchemaVersion>
18+
</PropertyGroup>
19+
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
20+
</Project>

samples/SampleApp/project.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"version": "1.0.0-*",
3+
4+
"dependencies": {
5+
"Microsoft.AspNet.Http": "1.0.0-*"
6+
},
7+
8+
"commands": {
9+
"SampleApp": "SampleApp"
10+
},
11+
12+
"frameworks": {
13+
"dnx451": { }
14+
}
15+
}

src/Microsoft.AspNet.Http.Abstractions/IHeaderDictionary.cs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,30 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System.Collections.Generic;
5-
using System.Diagnostics.CodeAnalysis;
5+
using Microsoft.AspNet.Primitives;
66

77
namespace Microsoft.AspNet.Http
88
{
99
/// <summary>
1010
/// Represents request and response headers
1111
/// </summary>
12-
public interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>
12+
public interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, StringValues>
1313
{
14+
// This property is duplicated to resolve an ambiguity between IReadableStringCollection and IDictionary<string, StringValues>
1415
/// <summary>
15-
/// Get or sets the associated value from the collection as a single string.
16+
///
1617
/// </summary>
17-
/// <param name="key">The header name.</param>
18-
/// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>
19-
new string this[string key] { get; set; }
18+
/// <param name="key"></param>
19+
/// <returns>The stored value, or StringValues.Empty if the key is not present.</returns>
20+
new StringValues this[string key] { get; set; }
2021

21-
// This property is duplicated to resolve an ambiguity between IReadableStringCollection.Count and IDictionary<string, string[]>.Count
22+
// This property is duplicated to resolve an ambiguity between IReadableStringCollection.Count and IDictionary<string, StringValues>.Count
2223
/// <summary>
2324
/// Gets the number of elements contained in the collection.
2425
/// </summary>
2526
new int Count { get; }
2627

27-
// This property is duplicated to resolve an ambiguity between IReadableStringCollection.Keys and IDictionary<string, string[]>.Keys
28+
// This property is duplicated to resolve an ambiguity between IReadableStringCollection.Keys and IDictionary<string, StringValues>.Keys
2829
/// <summary>
2930
/// Gets a collection containing the keys.
3031
/// </summary>
@@ -36,21 +37,14 @@ public interface IHeaderDictionary : IReadableStringCollection, IDictionary<stri
3637
/// </summary>
3738
/// <param name="key">The header name.</param>
3839
/// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>
39-
IList<string> GetCommaSeparatedValues(string key);
40+
StringValues GetCommaSeparatedValues(string key);
4041

4142
/// <summary>
42-
/// Add a new value. Appends to the header if already present
43+
/// Add a new value. Appends to the header list if already present
4344
/// </summary>
4445
/// <param name="key">The header name.</param>
4546
/// <param name="value">The header value.</param>
46-
void Append(string key, string value);
47-
48-
/// <summary>
49-
/// Add new values. Each item remains a separate array entry.
50-
/// </summary>
51-
/// <param name="key">The header name.</param>
52-
/// <param name="values">The header values.</param>
53-
void AppendValues(string key, params string[] values);
47+
void Append(string key, StringValues value);
5448

5549
/// <summary>
5650
/// Quotes any values containing comas, and then coma joins all of the values with any existing values.
@@ -59,21 +53,6 @@ public interface IHeaderDictionary : IReadableStringCollection, IDictionary<stri
5953
/// <param name="values">The header values.</param>
6054
void AppendCommaSeparatedValues(string key, params string[] values);
6155

62-
/// <summary>
63-
/// Sets a specific header value.
64-
/// </summary>
65-
/// <param name="key">The header name.</param>
66-
/// <param name="value">The header value.</param>
67-
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Set", Justification = "Re-evaluate later.")]
68-
void Set(string key, string value);
69-
70-
/// <summary>
71-
/// Sets the specified header values without modification.
72-
/// </summary>
73-
/// <param name="key">The header name.</param>
74-
/// <param name="values">The header values.</param>
75-
void SetValues(string key, params string[] values);
76-
7756
/// <summary>
7857
/// Quotes any values containing comas, and then coma joins all of the values.
7958
/// </summary>

src/Microsoft.AspNet.Http.Abstractions/IReadableStringCollection.cs

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System.Collections.Generic;
5-
using System.Diagnostics.CodeAnalysis;
5+
using Microsoft.AspNet.Primitives;
66

77
namespace Microsoft.AspNet.Http
88
{
99
/// <summary>
1010
/// Accessors for headers, query, forms, etc.
1111
/// </summary>
12-
public interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>
12+
public interface IReadableStringCollection : IEnumerable<KeyValuePair<string, StringValues>>
1313
{
1414
/// <summary>
15-
/// Get the associated value from the collection. Multiple values will be merged.
16-
/// Returns null if the key is not present.
15+
/// Get the associated value from the collection.
16+
/// Returns StringValues.Empty if the key is not present.
1717
/// </summary>
1818
/// <param name="key"></param>
1919
/// <returns></returns>
20-
string this[string key] { get; }
20+
StringValues this[string key] { get; }
2121

2222
/// <summary>
2323
/// Gets the number of elements contained in the collection.
@@ -35,22 +35,5 @@ public interface IReadableStringCollection : IEnumerable<KeyValuePair<string, st
3535
/// <param name="key"></param>
3636
/// <returns></returns>
3737
bool ContainsKey(string key);
38-
39-
/// <summary>
40-
/// Get the associated value from the collection. Multiple values will be merged.
41-
/// Returns null if the key is not present.
42-
/// </summary>
43-
/// <param name="key"></param>
44-
/// <returns></returns>
45-
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Re-evaluate later.")]
46-
string Get(string key);
47-
48-
/// <summary>
49-
/// Get the associated values from the collection in their original format.
50-
/// Returns null if the key is not present.
51-
/// </summary>
52-
/// <param name="key"></param>
53-
/// <returns></returns>
54-
IList<string> GetValues(string key);
5538
}
5639
}

src/Microsoft.AspNet.Http.Abstractions/QueryString.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Text;
7+
using Microsoft.AspNet.Primitives;
78
using Microsoft.Framework.Internal;
89
using Microsoft.Framework.WebEncoders;
910

@@ -143,7 +144,7 @@ public static QueryString Create(IEnumerable<KeyValuePair<string, string>> param
143144
/// </summary>
144145
/// <param name="parameters"></param>
145146
/// <returns>The resulting QueryString</returns>
146-
public static QueryString Create(IEnumerable<KeyValuePair<string, string[]>> parameters)
147+
public static QueryString Create(IEnumerable<KeyValuePair<string, StringValues>> parameters)
147148
{
148149
var builder = new StringBuilder();
149150
bool first = true;

src/Microsoft.AspNet.Http.Abstractions/WebSocketManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System.Collections.Generic;
54
using System.Net.WebSockets;
65
using System.Threading.Tasks;
6+
using Microsoft.AspNet.Primitives;
77

88
namespace Microsoft.AspNet.Http
99
{
1010
public abstract class WebSocketManager
1111
{
1212
public abstract bool IsWebSocketRequest { get; }
1313

14-
public abstract IList<string> WebSocketRequestedProtocols { get; }
14+
public abstract StringValues WebSocketRequestedProtocols { get; }
1515

1616
public virtual Task<WebSocket> AcceptWebSocketAsync()
1717
{

src/Microsoft.AspNet.Http.Extensions/HeaderDictionaryTypeExtensions.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Linq;
77
using System.Reflection;
88
using Microsoft.AspNet.Http.Headers;
9+
using Microsoft.AspNet.Primitives;
910
using Microsoft.Framework.Internal;
1011
using Microsoft.Net.Http.Headers;
1112

@@ -50,7 +51,7 @@ internal static void SetList<T>([NotNull] this IHeaderDictionary headers, [NotNu
5051
}
5152
else
5253
{
53-
headers.SetValues(name, values.Select(value => value.ToString()).ToArray());
54+
headers[name] = values.Select(value => value.ToString()).ToArray();
5455
}
5556
}
5657

@@ -98,7 +99,7 @@ internal static T Get<T>([NotNull] this IHeaderDictionary headers, string name)
9899
}
99100

100101
var value = headers[name];
101-
if (string.IsNullOrWhiteSpace(value))
102+
if (StringValues.IsNullOrEmpty(value))
102103
{
103104
return default(T);
104105
}
@@ -112,11 +113,11 @@ internal static IList<T> GetList<T>([NotNull] this IHeaderDictionary headers, st
112113
if (KnownListParsers.TryGetValue(typeof(T), out temp))
113114
{
114115
var func = (Func<IList<string>, IList<T>>)temp;
115-
return func(headers.GetValues(name));
116+
return func(headers[name]);
116117
}
117118

118-
var values = headers.GetValues(name);
119-
if (values == null || !values.Any())
119+
var values = headers[name];
120+
if (StringValues.IsNullOrEmpty(values))
120121
{
121122
return null;
122123
}
@@ -158,7 +159,7 @@ private static T GetViaReflection<T>(string value)
158159
return default(T);
159160
}
160161

161-
private static IList<T> GetListViaReflection<T>(IList<string> values)
162+
private static IList<T> GetListViaReflection<T>(StringValues values)
162163
{
163164
// TODO: Cache the reflected type for later? Only if success?
164165
var type = typeof(T);

src/Microsoft.AspNet.Http.Extensions/RequestHeaders.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ public void Append([NotNull] string name, [NotNull] object value)
285285

286286
public void AppendList<T>([NotNull] string name, [NotNull] IList<T> values)
287287
{
288-
Headers.AppendValues(name, values.Select(value => value.ToString()).ToArray());
288+
Headers.Append(name, values.Select(value => value.ToString()).ToArray());
289289
}
290290
}
291291
}

src/Microsoft.AspNet.Http.Extensions/ResponseHeaders.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public void Append([NotNull] string name, [NotNull] object value)
182182

183183
public void AppendList<T>([NotNull] string name, [NotNull] IList<T> values)
184184
{
185-
Headers.AppendValues(name, values.Select(value => value.ToString()).ToArray());
185+
Headers.Append(name, values.Select(value => value.ToString()).ToArray());
186186
}
187187
}
188188
}

0 commit comments

Comments
 (0)