Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New ctor for FormUrlEncodedContent accepting Dictionary #44458

Closed
ManickaP opened this issue Nov 10, 2020 · 5 comments · Fixed by #55410
Closed

New ctor for FormUrlEncodedContent accepting Dictionary #44458

ManickaP opened this issue Nov 10, 2020 · 5 comments · Fixed by #55410
Assignees
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Net.Http
Milestone

Comments

@ManickaP
Copy link
Member

ManickaP commented Nov 10, 2020

Background and Motivation

#38494

Once we annotated FormUrlEncodedContent we have prevented people from using the ctor with Dictionary. Dictionary's TKey cannot be null, colliding with key nullability in IEnumerable<KeyValuePair<string?, string?>>.

Changing the existing API might be problematic since the type have always accepted null keys and replaces them with an empty string:

Proposal is to add a new constructor accepting IDictionary<string, string?> and thus enabling uses like:

var nullableValueDictionary = new Dictionary<string, string?>
{
    ["foo"] = "bar"
};

_ = new FormUrlEncodedContent(nullableValueDictionary);

Proposed API

namespace  System.Net.Http
{
    public partial class FormUrlEncodedContent : ByteArrayContent
    {
+       public FormUrlEncodedContent(IDictionary<string, string?> dictionary);

        // Existing ctor
        public FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection);
        ...
    }
}   

Alternative Designs

Making the value non-null as well will ease the usage even more. Enabling usage with Dictionary<string, string>:

var dictionary = new Dictionary<string, string>
{
    ["foo"] = "bar"
};
_ = new FormUrlEncodedContent(dictionary);

Api proposal:

namespace  System.Net.Http
{
    public partial class FormUrlEncodedContent : ByteArrayContent
    {
        // non-nullable value as well, we cannot overload on nullability so we cannot add this later, we must chose one
+       public FormUrlEncodedContent(IDictionary<string, string> dictionary);

        // Existing ctor
        public FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)
        ...
    }
}   

Usage Examples

var nullableValueDictionary = new Dictionary<string, string?>
{
    ["foo"] = "bar"
};
_ = new FormUrlEncodedContent(nullableValueDictionary);
@ManickaP ManickaP added api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Net.Http labels Nov 10, 2020
@ghost
Copy link

ghost commented Nov 10, 2020

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.


Issue meta data
Issue content: ## Background and Motivation https://github.com//issues/38494

Once we annotated FormUrlEncodedContent we have prevented people from using the ctor with Dictionary. Dictionary's TKey cannot be null, colliding with key nullability in IEnumerable<KeyValuePair<string?, string?>>.

Changing the existing API might be problematic since the type have always accepted null keys and replaces them with an empty string:

Proposal is to add a new constructor accepting IDictionary<string, string?> and thus enabling uses like:

var nullableValueDictionary = new Dictionary<string, string?>
{
    ["foo"] = "bar"
};

_ = new FormUrlEncodedContent(nullableValueDictionary);

Proposed API

namespace  System.Net.Http
{
    public partial class FormUrlEncodedContent : ByteArrayContent
    {
+       public FormUrlEncodedContent(IDictionary<string, string?> dictionary);

        // Existing ctor
        public FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection);
        ...
    }
}   

Alternative Designs

Making the value non-null as well will ease the usage even more. Enabling usage with Dictionary<string, string>:

var dictionary = new Dictionary<string, string>
{
    ["foo"] = "bar"
};
_ = new FormUrlEncodedContent(dictionary);

Api proposal:

namespace  System.Net.Http
{
    public partial class FormUrlEncodedContent : ByteArrayContent
    {
        // non-nullable value as well, we cannot overload on nullability so we cannot add this later, we must chose one
+       public FormUrlEncodedContent(IDictionary<string, string> dictionary);

        // Existing ctor
        public FormUrlEncodedContent(IEnumerable<KeyValuePair<string?, string?>> nameValueCollection)
        ...
    }
}   

Usage Examples

var nullableValueDictionary = new Dictionary<string, string?>
{
    ["foo"] = "bar"
};
_ = new FormUrlEncodedContent(nullableValueDictionary);
```</td>
  </tr>
  <tr>
    <td>Issue author:</td>
    <td>ManickaP</td>
  </tr>
  <tr>
    <td>Assignees:</td>
    <td>-</td>
  </tr>
  <tr>
    <td>Milestone:</td>
    <td>-</td>
  </tr>
  </table>
  </details>

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Nov 10, 2020
@karelz
Copy link
Member

karelz commented Dec 2, 2020

Triage: Next step -- research if FromUrlEncodedContent can meaningfully use empty string (aka null passed in). If yes, we are ok with this API. Otherwise, we should just make the technical breaking change.

@karelz
Copy link
Member

karelz commented Dec 2, 2020

@ManickaP can you please look at it when you get a chance, so that we can make decision? Thanks!

@karelz karelz added this to the 6.0.0 milestone Dec 2, 2020
@LeaFrock
Copy link
Contributor

LeaFrock commented Dec 3, 2020

IMO, I prefer public FormUrlEncodedContent(IDictionary<string, string?> dictionary). It makes no breaking changes, and callers can write codes like below,

var nullableValueDictionary = new Dictionary<string, string?>
{
    ["foo"] = default //use easier syntax sugar instead of string.Empty(or "" which is possible to make a typo like " ") and don't worry about exceptions
};
_ = new FormUrlEncodedContent(nullableValueDictionary);

@karelz @ManickaP I can make a PR to finish it if you have more imporant things to deal with.

BTW, I think Encode here can be optimized.

  // Escape spaces as '+'.
  return Uri.EscapeDataString(data).Replace("%20", "+");

Since this method will be used every time on the keys and values, may String.Replace be removed if we have another method for escaping data string? It's just due to the difference of treating WHITESPACE by W3C and by RFC 2396. Need I to create a stand-alone issue about it?

@karelz
Copy link
Member

karelz commented Jan 21, 2021

Triage: Some more tests are needed to determine if we need new API - @ManickaP is on point.

@karelz karelz removed the untriaged New issue has not been triaged by the area owner label Feb 2, 2021
@karelz karelz modified the milestones: 6.0.0, Future May 4, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jul 9, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jul 9, 2021
@karelz karelz modified the milestones: Future, 6.0.0 Jul 15, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Net.Http
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants