Skip to content

Commit

Permalink
Make wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
twsouthwick committed Mar 22, 2022
1 parent 0f74672 commit 06bda2c
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 131 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;

namespace System.Web.Internal;

internal class FormCollectionReadOnlyDictionary : IReadOnlyDictionary<string, StringValues>
{
private readonly IFormCollection _form;

public FormCollectionReadOnlyDictionary(IFormCollection form)
{
_form = form;
}

public StringValues this[string key] => _form[key];

public IEnumerable<string> Keys => _form.Keys;

public IEnumerable<StringValues> Values
{
get
{
foreach (var item in _form)
{
yield return item.Value;
}
}
}

public int Count => _form.Count;

public bool ContainsKey(string key) => _form.ContainsKey(key);

public IEnumerator<KeyValuePair<string, StringValues>> GetEnumerator() => _form.GetEnumerator();

public bool TryGetValue(string key, [MaybeNullWhen(false)] out StringValues value) => _form.TryGetValue(key, out value);

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
28 changes: 18 additions & 10 deletions src/SystemWebAdapters/src/Internal/NameValueCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Primitives;
Expand All @@ -11,21 +13,27 @@ namespace System.Web.Internal;

internal static class NameValueCollectionExtensions
{
public static NameValueCollection ToNameValueCollection(this IQueryCollection query) => ToReadOnlyNameValueCollection(query.Count, query);

public static NameValueCollection ToNameValueCollection(this IFormCollection form) => ToReadOnlyNameValueCollection(form.Count, form);

public static NameValueCollection ToNameValueCollection(this IHeaderDictionary headers) => new StringValuesDictionaryNameValueCollection(headers);
public static NameValueCollection ToNameValueCollection(this IQueryCollection query)
{
if (query.Count == 0)
{
return StringValuesReadOnlyDictionaryNameValueCollection.Empty;
}

public static NameValueCollection ToNameValueCollection(this IServerVariablesFeature serverVariables) => new ServerVariablesNameValueCollection(serverVariables);
return new StringValuesReadOnlyDictionaryNameValueCollection(new QueryCollectionReadOnlyDictionary(query));
}

private static NameValueCollection ToReadOnlyNameValueCollection(int count, IEnumerable<KeyValuePair<string, StringValues>> items)
public static NameValueCollection ToNameValueCollection(this IFormCollection form)
{
if (count == 0)
if (form.Count == 0)
{
return StringValuesNameValueCollection.Empty;
return StringValuesReadOnlyDictionaryNameValueCollection.Empty;
}

return new StringValuesNameValueCollection(items);
return new StringValuesReadOnlyDictionaryNameValueCollection(new FormCollectionReadOnlyDictionary(form));
}

public static NameValueCollection ToNameValueCollection(this IHeaderDictionary headers) => new StringValuesDictionaryNameValueCollection(headers);

public static NameValueCollection ToNameValueCollection(this IServerVariablesFeature serverVariables) => new ServerVariablesNameValueCollection(serverVariables);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;

namespace System.Web.Internal;

internal class QueryCollectionReadOnlyDictionary : IReadOnlyDictionary<string, StringValues>
{
private readonly IQueryCollection _query;

public QueryCollectionReadOnlyDictionary(IQueryCollection query)
{
_query = query;
}

public StringValues this[string key] => _query[key];

public IEnumerable<string> Keys => _query.Keys;

public IEnumerable<StringValues> Values
{
get
{
foreach (var item in _query)
{
yield return item.Value;
}
}
}

public int Count => _query.Count;

public bool ContainsKey(string key) => _query.ContainsKey(key);

public IEnumerator<KeyValuePair<string, StringValues>> GetEnumerator() => _query.GetEnumerator();

public bool TryGetValue(string key, [MaybeNullWhen(false)] out StringValues value) => _query.TryGetValue(key, out value);

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using System.Collections;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using Microsoft.AspNetCore.Http.Features;

namespace System.Web.Internal
{
internal class ServerVariablesNameValueCollection : NameValueCollection
internal class ServerVariablesNameValueCollection : WrappingNameValueCollection
{
private const string EnumerationErrorMessage = "ASP.NET Core doesn't support enumerating server variables.";
private const string IndexErrorMessage = "ASP.NET Core doesn't support accessing server variables by index.";
private const string SerializationErrorMessage = "ASP.NET Core doesn't suppor serialization of server variables.";

private readonly IServerVariablesFeature _serverVariables;
Expand All @@ -33,14 +32,6 @@ public override void Add(string? name, string? value)
_serverVariables[name] = value;
}

public override KeysCollection Keys => throw new PlatformNotSupportedException("KeysCollection is not supported as Get(int) is not available.");

public override string? Get(int index) => throw new PlatformNotSupportedException(IndexErrorMessage);

public override string? GetKey(int index) => throw new PlatformNotSupportedException(IndexErrorMessage);

public override string[]? GetValues(int index) => throw new PlatformNotSupportedException(IndexErrorMessage);

public override string[]? GetValues(string? name)
{
if (name is not null && _serverVariables[name] is string result)
Expand Down Expand Up @@ -87,6 +78,6 @@ public override void Set(string? name, string? value)

public override void GetObjectData(SerializationInfo info, StreamingContext context) => throw new PlatformNotSupportedException(SerializationErrorMessage);

public override void OnDeserialization(object? sender)=> throw new PlatformNotSupportedException(SerializationErrorMessage);
public override void OnDeserialization(object? sender) => throw new PlatformNotSupportedException(SerializationErrorMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.Extensions.Primitives;

namespace System.Web.Internal
{
internal class StringValuesDictionaryNameValueCollection : NameValueCollection
internal class StringValuesDictionaryNameValueCollection : WrappingNameValueCollection
{
private const string GetByIntNotSupported = "Get by index is not available on this platform";

private readonly IDictionary<string, StringValues> _headers;
private readonly IDictionary<string, StringValues> _values;

public StringValuesDictionaryNameValueCollection(IDictionary<string, StringValues> headers)
{
_headers = headers;
_values = headers;
}

public override string?[] AllKeys => _headers.Keys.ToArray();
public override string?[] AllKeys => _values.Keys.ToArray();

public override int Count => _headers.Count;
public override int Count => _values.Count;

public override void Add(string? name, string? value)
{
Expand All @@ -28,39 +25,24 @@ public override void Add(string? name, string? value)
return;
}

if (_headers.TryGetValue(name, out var existing))
if (_values.TryGetValue(name, out var existing))
{
_headers[name] = StringValues.Concat(existing, value);
_values[name] = StringValues.Concat(existing, value);
}
else
{
_headers.Add(name, value);
_values.Add(name, value);
}
}

public override KeysCollection Keys => throw new PlatformNotSupportedException("KeysCollection is not supported as Get(int) is not available.");

public override string? Get(int index) => throw new PlatformNotSupportedException(GetByIntNotSupported);

public override string? GetKey(int index) => throw new PlatformNotSupportedException(GetByIntNotSupported);

public override string[]? GetValues(int index) => throw new PlatformNotSupportedException(GetByIntNotSupported);

public override string[]? GetValues(string? name)
{
if (name is not null && _headers.TryGetValue(name, out var values))
{
return values;
}

return null;
}
=> name is not null && _values.TryGetValue(name, out var values) ? values : default;

public override void Remove(string? name)
{
if (name is not null)
{
_headers.Remove(name);
_values.Remove(name);
}
}

Expand All @@ -71,21 +53,14 @@ public override void Set(string? name, string? value)
return;
}

_headers[name] = value;
_values[name] = value;
}

public override string? Get(string? name)
{
if (name is not null && _headers.TryGetValue(name, out var value))
{
return value;
}

return null;
}
=> name is not null && _values.TryGetValue(name, out var values) ? values : default;

public override void Clear() => _headers.Clear();
public override void Clear() => _values.Clear();

public override IEnumerator GetEnumerator() => _headers.Keys.GetEnumerator();
public override IEnumerator GetEnumerator() => _values.Keys.GetEnumerator();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.Extensions.Primitives;

namespace System.Web.Internal
{
internal class StringValuesReadOnlyDictionaryNameValueCollection : WrappingNameValueCollection
{
private readonly IReadOnlyDictionary<string, StringValues> _values;

public static NameValueCollection Empty { get; } = new StringValuesReadOnlyDictionaryNameValueCollection();

public StringValuesReadOnlyDictionaryNameValueCollection()
: this(new Dictionary<string, StringValues>())
{
}

public StringValuesReadOnlyDictionaryNameValueCollection(IReadOnlyDictionary<string, StringValues> values)
{
_values = values;
IsReadOnly = true;
}

public override string?[] AllKeys => _values.Keys.ToArray();

public override int Count => _values.Count;

public override string[]? GetValues(string? name)
=> name is not null && _values.TryGetValue(name, out var values) ? values : default;

public override string? Get(string? name)
=> name is not null && _values.TryGetValue(name, out var values) ? values : default;

public override IEnumerator GetEnumerator() => _values.Keys.GetEnumerator();
}
}
17 changes: 17 additions & 0 deletions src/SystemWebAdapters/src/Internal/WrappingNameValueCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Specialized;

namespace System.Web.Internal
{
internal abstract class WrappingNameValueCollection : NameValueCollection
{
private const string IndexErrorMessage = "ASP.NET Core doesn't support accessing server variables by index.";

public sealed override string? Get(int index) => throw new PlatformNotSupportedException(IndexErrorMessage);

public sealed override string? GetKey(int index) => throw new PlatformNotSupportedException(IndexErrorMessage);

public sealed override string[]? GetValues(int index) => throw new PlatformNotSupportedException(IndexErrorMessage);

public sealed override KeysCollection Keys => throw new PlatformNotSupportedException("KeysCollection is not supported as Get(int) is not available.");
}
}
4 changes: 2 additions & 2 deletions src/SystemWebAdapters/test/HttpRequestTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ public void Form()

// Assert
Assert.Same(formCollection1, formCollection2);
Assert.IsType<StringValuesNameValueCollection>(formCollection1);
Assert.IsType<StringValuesReadOnlyDictionaryNameValueCollection>(formCollection1);
}

[Fact]
Expand Down Expand Up @@ -755,7 +755,7 @@ public void Query()

// Assert
Assert.Same(queryCollection1, queryCollection2);
Assert.IsType<StringValuesNameValueCollection>(queryCollection1);
Assert.IsType<StringValuesReadOnlyDictionaryNameValueCollection>(queryCollection1);
}
}
}
Loading

0 comments on commit 06bda2c

Please sign in to comment.