Skip to content

Commit 5b1c818

Browse files
sebastienroscaptainsafiaJamesNK
authored
Improve IFormCollection.Items documentation (#44372)
Fixes #36712 Co-authored-by: Safia Abdalla <[email protected]> Co-authored-by: James Newton-King <[email protected]>
1 parent cb71b00 commit 5b1c818

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

src/Http/Http.Abstractions/src/HttpRequest.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,24 @@ public abstract class HttpRequest
120120
/// <summary>
121121
/// Gets or sets the request body as a form.
122122
/// </summary>
123+
/// <exception cref="System.InvalidOperationException">
124+
/// incorrect content-type.
125+
/// </exception>
126+
/// <remarks>
127+
/// <para>
128+
/// Invoking this property could result in thread exhaustion since it's wrapping an asynchronous implementation.
129+
/// To prevent this the method <see cref="ReadFormAsync(CancellationToken)"/> can be used.
130+
/// For more information, see <see href="https://aka.ms/aspnet/forms-async" />.
131+
/// </para>
132+
/// </remarks>
123133
public abstract IFormCollection Form { get; set; }
124134

125135
/// <summary>
126136
/// Reads the request body if it is a form.
127137
/// </summary>
138+
/// <exception cref="System.InvalidOperationException">
139+
/// incorrect content-type.
140+
/// </exception>
128141
/// <returns></returns>
129142
public abstract Task<IFormCollection> ReadFormAsync(CancellationToken cancellationToken = new CancellationToken());
130143

src/Http/Http.Features/src/IFormCollection.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,24 @@ public interface IFormCollection : IEnumerable<KeyValuePair<string, StringValues
7777
/// <exception cref="System.ArgumentNullException">
7878
/// key is null.
7979
/// </exception>
80+
/// <exception cref="System.InvalidOperationException">
81+
/// incorrect content-type.
82+
/// </exception>
8083
/// <remarks>
84+
/// <para>
8185
/// <see cref="IFormCollection" /> has a different indexer contract than
8286
/// <see cref="IDictionary{TKey, TValue}" />, as it will return <c>StringValues.Empty</c> for missing entries
8387
/// rather than throwing an Exception.
88+
/// </para>
89+
/// <para>
90+
/// This indexer can only be used on POST requests. Otherwise an exception of type
91+
/// <see cref="System.InvalidOperationException" /> is thrown.
92+
/// </para>
93+
/// <para>
94+
/// Invoking this property could result in thread exhaustion since it's wrapping an asynchronous implementation.
95+
/// The <c>HttpRequest.ReadFormAsync(CancellationToken)</c> method can get the form without blocking.
96+
/// For more information, see <see href="https://aka.ms/aspnet/forms-async" />.
97+
/// </para>
8498
/// </remarks>
8599
StringValues this[string key] { get; }
86100

src/Http/Http/src/Features/FormFeature.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@ public IFormCollection ReadForm()
101101

102102
if (!HasFormContentType)
103103
{
104-
throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType);
104+
throw new InvalidOperationException("This request does not have a Content-Type header. Forms are available from requests with bodies like POSTs and a form Content-Type of either application/x-www-form-urlencoded or multipart/form-data.");
105105
}
106106

107-
// TODO: Issue #456 Avoid Sync-over-Async http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx
108-
// TODO: How do we prevent thread exhaustion?
107+
// c.f., https://aka.ms/aspnet/forms-async
109108
return ReadFormAsync().GetAwaiter().GetResult();
110109
}
111110

0 commit comments

Comments
 (0)