This repository has been archived by the owner on Dec 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
MvcOptions.cs
493 lines (457 loc) · 26 KB
/
MvcOptions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Microsoft.AspNetCore.Mvc
{
/// <summary>
/// Provides programmatic configuration for the MVC framework.
/// </summary>
public class MvcOptions : IEnumerable<ICompatibilitySwitch>
{
private int _maxModelStateErrors = ModelStateDictionary.DefaultMaxAllowedErrors;
// See CompatibilitySwitch.cs for guide on how to implement these.
private readonly CompatibilitySwitch<bool> _allowBindingHeaderValuesToNonStringModelTypes;
private readonly CompatibilitySwitch<bool> _allowCombiningAuthorizeFilters;
private readonly CompatibilitySwitch<bool> _allowValidatingTopLevelNodes;
private readonly CompatibilitySwitch<InputFormatterExceptionPolicy> _inputFormatterExceptionPolicy;
private readonly CompatibilitySwitch<bool> _suppressBindingUndefinedValueToEnumType;
private readonly CompatibilitySwitch<bool> _enableEndpointRouting;
private readonly NullableCompatibilitySwitch<int> _maxValidationDepth;
private readonly CompatibilitySwitch<bool> _allowShortCircuitingValidationWhenNoValidatorsArePresent;
private readonly ICompatibilitySwitch[] _switches;
/// <summary>
/// Creates a new instance of <see cref="MvcOptions"/>.
/// </summary>
public MvcOptions()
{
CacheProfiles = new Dictionary<string, CacheProfile>(StringComparer.OrdinalIgnoreCase);
Conventions = new List<IApplicationModelConvention>();
Filters = new FilterCollection();
FormatterMappings = new FormatterMappings();
InputFormatters = new FormatterCollection<IInputFormatter>();
OutputFormatters = new FormatterCollection<IOutputFormatter>();
ModelBinderProviders = new List<IModelBinderProvider>();
ModelBindingMessageProvider = new DefaultModelBindingMessageProvider();
ModelMetadataDetailsProviders = new List<IMetadataDetailsProvider>();
ModelValidatorProviders = new List<IModelValidatorProvider>();
ValueProviderFactories = new List<IValueProviderFactory>();
_allowCombiningAuthorizeFilters = new CompatibilitySwitch<bool>(nameof(AllowCombiningAuthorizeFilters));
_allowBindingHeaderValuesToNonStringModelTypes = new CompatibilitySwitch<bool>(nameof(AllowBindingHeaderValuesToNonStringModelTypes));
_allowValidatingTopLevelNodes = new CompatibilitySwitch<bool>(nameof(AllowValidatingTopLevelNodes));
_inputFormatterExceptionPolicy = new CompatibilitySwitch<InputFormatterExceptionPolicy>(nameof(InputFormatterExceptionPolicy), InputFormatterExceptionPolicy.AllExceptions);
_suppressBindingUndefinedValueToEnumType = new CompatibilitySwitch<bool>(nameof(SuppressBindingUndefinedValueToEnumType));
_enableEndpointRouting = new CompatibilitySwitch<bool>(nameof(EnableEndpointRouting));
_maxValidationDepth = new NullableCompatibilitySwitch<int>(nameof(MaxValidationDepth));
_allowShortCircuitingValidationWhenNoValidatorsArePresent = new CompatibilitySwitch<bool>(nameof(AllowShortCircuitingValidationWhenNoValidatorsArePresent));
_switches = new ICompatibilitySwitch[]
{
_allowCombiningAuthorizeFilters,
_allowBindingHeaderValuesToNonStringModelTypes,
_allowValidatingTopLevelNodes,
_inputFormatterExceptionPolicy,
_suppressBindingUndefinedValueToEnumType,
_enableEndpointRouting,
_maxValidationDepth,
_allowShortCircuitingValidationWhenNoValidatorsArePresent,
};
}
/// <summary>
/// Gets or sets a value that determines if routing should use endpoints internally, or if legacy routing
/// logic should be used. Endpoint routing is used to match HTTP requests to MVC actions, and to generate
/// URLs with <see cref="IUrlHelper"/>.
/// </summary>
/// <value>
/// The default value is <see langword="true"/> if the version is
/// <see cref="CompatibilityVersion.Version_2_2"/> or later; <see langword="false"/> otherwise.
/// </value>
/// <remarks>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take
/// precedence over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// lower then this setting will have the value <see langword="false"/> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_2"/> or
/// higher then this setting will have the value <see langword="true"/> unless explicitly configured.
/// </para>
/// </remarks>
public bool EnableEndpointRouting
{
get => _enableEndpointRouting.Value;
set => _enableEndpointRouting.Value = value;
}
/// <summary>
/// Gets or sets the flag which decides whether body model binding (for example, on an
/// action method parameter with <see cref="FromBodyAttribute"/>) should treat empty
/// input as valid. <see langword="false"/> by default.
/// </summary>
/// <example>
/// When <see langword="false"/>, actions that model bind the request body (for example,
/// using <see cref="FromBodyAttribute"/>) will register an error in the
/// <see cref="ModelStateDictionary"/> if the incoming request body is empty.
/// </example>
public bool AllowEmptyInputInBodyModelBinding { get; set; }
/// <summary>
/// Gets or sets a value that determines if policies on instances of <see cref="AuthorizeFilter" />
/// will be combined into a single effective policy. The default value of the property is <c>false</c>.
/// </summary>
/// <remarks>
/// <para>
/// Authorization policies are designed such that multiple authorization policies applied to an endpoint
/// should be combined and executed a single policy. The <see cref="AuthorizeFilter"/> (commonly applied
/// by <see cref="AuthorizeAttribute"/>) can be applied globally, to controllers, and to actions - which
/// specifies multiple authorization policies for an action. In all ASP.NET Core releases prior to 2.1
/// these multiple policies would not combine as intended. This compatibility switch configures whether the
/// old (unintended) behavior or the new combining behavior will be used when multiple authorization policies
/// are applied.
/// </para>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take precedence
/// over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_0"/> then
/// this setting will have the value <c>false</c> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// higher then this setting will have the value <c>true</c> unless explicitly configured.
/// </para>
/// </remarks>
public bool AllowCombiningAuthorizeFilters
{
get => _allowCombiningAuthorizeFilters.Value;
set => _allowCombiningAuthorizeFilters.Value = value;
}
/// <summary>
/// Gets or sets a value that determines if <see cref="HeaderModelBinder"/> should bind to types other than
/// <see cref="string"/> or a collection of <see cref="string"/>. If set to <c>true</c>,
/// <see cref="HeaderModelBinder"/> would bind to simple types (like <see cref="string"/>, <see cref="int"/>,
/// <see cref="Enum"/>, <see cref="bool"/> etc.) or a collection of simple types. The default value of the
/// property is <c>false</c>.
/// </summary>
/// <remarks>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take precedence
/// over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_0"/> then
/// this setting will have the value <c>false</c> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// higher then this setting will have the value <c>true</c> unless explicitly configured.
/// </para>
/// </remarks>
public bool AllowBindingHeaderValuesToNonStringModelTypes
{
get => _allowBindingHeaderValuesToNonStringModelTypes.Value;
set => _allowBindingHeaderValuesToNonStringModelTypes.Value = value;
}
/// <summary>
/// Gets or sets a value that determines if model bound action parameters, controller properties, page handler
/// parameters, or page model properties are validated (in addition to validating their elements or
/// properties). If set to <see langword="true"/>, <see cref="BindRequiredAttribute"/> and
/// <c>ValidationAttribute</c>s on these top-level nodes are checked. Otherwise, such attributes are ignored.
/// </summary>
/// <value>
/// The default value is <see langword="true"/> if the version is
/// <see cref="CompatibilityVersion.Version_2_1"/> or later; <see langword="false"/> otherwise.
/// </value>
/// <remarks>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take
/// precedence over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_0"/> then
/// this setting will have the value <see langword="false"/> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// higher then this setting will have the value <see langword="true"/> unless explicitly configured.
/// </para>
/// </remarks>
public bool AllowValidatingTopLevelNodes
{
get => _allowValidatingTopLevelNodes.Value;
set => _allowValidatingTopLevelNodes.Value = value;
}
/// <summary>
/// Gets a Dictionary of CacheProfile Names, <see cref="CacheProfile"/> which are pre-defined settings for
/// response caching.
/// </summary>
public IDictionary<string, CacheProfile> CacheProfiles { get; }
/// <summary>
/// Gets a list of <see cref="IApplicationModelConvention"/> instances that will be applied to
/// the <see cref="ApplicationModel"/> when discovering actions.
/// </summary>
public IList<IApplicationModelConvention> Conventions { get; }
/// <summary>
/// Gets a collection of <see cref="IFilterMetadata"/> which are used to construct filters that
/// apply to all actions.
/// </summary>
public FilterCollection Filters { get; }
/// <summary>
/// Used to specify mapping between the URL Format and corresponding media type.
/// </summary>
public FormatterMappings FormatterMappings { get; }
/// <summary>
/// Gets or sets a value which determines how the model binding system interprets exceptions thrown by an <see cref="IInputFormatter"/>.
/// The default value of the property is <see cref="InputFormatterExceptionPolicy.AllExceptions"/>.
/// </summary>
/// <remarks>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take precedence
/// over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_0"/> then
/// this setting will have the value <see cref="InputFormatterExceptionPolicy.AllExceptions"/> unless
/// explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// higher then this setting will have the value
/// <see cref="InputFormatterExceptionPolicy.MalformedInputExceptions"/> unless explicitly configured.
/// </para>
/// </remarks>
public InputFormatterExceptionPolicy InputFormatterExceptionPolicy
{
get => _inputFormatterExceptionPolicy.Value;
set => _inputFormatterExceptionPolicy.Value = value;
}
/// <summary>
/// Gets a list of <see cref="IInputFormatter"/>s that are used by this application.
/// </summary>
public FormatterCollection<IInputFormatter> InputFormatters { get; }
/// <summary>
/// Gets or sets a value indicating whether the model binding system will bind undefined values to
/// enum types. The default value of the property is <c>false</c>.
/// </summary>
/// <remarks>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take precedence
/// over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_0"/> then
/// this setting will have the value <c>false</c> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// higher then this setting will have the value <c>true</c> unless explicitly configured.
/// </para>
/// </remarks>
public bool SuppressBindingUndefinedValueToEnumType
{
get => _suppressBindingUndefinedValueToEnumType.Value;
set => _suppressBindingUndefinedValueToEnumType.Value = value;
}
/// <summary>
/// Gets or sets the flag to buffer the request body in input formatters. Default is <c>false</c>.
/// </summary>
public bool SuppressInputFormatterBuffering { get; set; } = false;
/// <summary>
/// Gets or sets the maximum number of validation errors that are allowed by this application before further
/// errors are ignored.
/// </summary>
public int MaxModelValidationErrors
{
get => _maxModelStateErrors;
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_maxModelStateErrors = value;
}
}
/// <summary>
/// Gets a list of <see cref="IModelBinderProvider"/>s used by this application.
/// </summary>
public IList<IModelBinderProvider> ModelBinderProviders { get; }
/// <summary>
/// Gets the default <see cref="ModelBinding.Metadata.ModelBindingMessageProvider"/>. Changes here are copied to the
/// <see cref="ModelMetadata.ModelBindingMessageProvider"/> property of all <see cref="ModelMetadata"/>
/// instances unless overridden in a custom <see cref="IBindingMetadataProvider"/>.
/// </summary>
public DefaultModelBindingMessageProvider ModelBindingMessageProvider { get; }
/// <summary>
/// Gets a list of <see cref="IMetadataDetailsProvider"/> instances that will be used to
/// create <see cref="ModelMetadata"/> instances.
/// </summary>
/// <remarks>
/// A provider should implement one or more of the following interfaces, depending on what
/// kind of details are provided:
/// <ul>
/// <li><see cref="IBindingMetadataProvider"/></li>
/// <li><see cref="IDisplayMetadataProvider"/></li>
/// <li><see cref="IValidationMetadataProvider"/></li>
/// </ul>
/// </remarks>
public IList<IMetadataDetailsProvider> ModelMetadataDetailsProviders { get; }
/// <summary>
/// Gets a list of <see cref="IModelValidatorProvider"/>s used by this application.
/// </summary>
public IList<IModelValidatorProvider> ModelValidatorProviders { get; }
/// <summary>
/// Gets a list of <see cref="IOutputFormatter"/>s that are used by this application.
/// </summary>
public FormatterCollection<IOutputFormatter> OutputFormatters { get; }
/// <summary>
/// Gets or sets the flag which causes content negotiation to ignore Accept header
/// when it contains the media type */*. <see langword="false"/> by default.
/// </summary>
public bool RespectBrowserAcceptHeader { get; set; }
/// <summary>
/// Gets or sets the flag which decides whether an HTTP 406 Not Acceptable response
/// will be returned if no formatter has been selected to format the response.
/// <see langword="false"/> by default.
/// </summary>
public bool ReturnHttpNotAcceptable { get; set; }
/// <summary>
/// Gets a list of <see cref="IValueProviderFactory"/> used by this application.
/// </summary>
public IList<IValueProviderFactory> ValueProviderFactories { get; }
/// <summary>
/// Gets or sets the SSL port that is used by this application when <see cref="RequireHttpsAttribute"/>
/// is used. If not set the port won't be specified in the secured URL e.g. https://localhost/path.
/// </summary>
public int? SslPort { get; set; }
/// <summary>
/// Gets or sets the default value for the Permanent property of <see cref="RequireHttpsAttribute"/>.
/// </summary>
public bool RequireHttpsPermanent { get; set; }
/// <summary>
/// Gets or sets the maximum depth to constrain the validation visitor when validating. Set to <see langword="null" />
/// to disable this feature.
/// <para>
/// <see cref="ValidationVisitor"/> traverses the object graph of the model being validated. For models
/// that are very deep or are infinitely recursive, validation may result in stack overflow.
/// </para>
/// <para>
/// When not <see langword="null"/>, <see cref="ValidationVisitor"/> will throw if
/// traversing an object exceeds the maximum allowed validation depth.
/// </para>
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take precedence
/// over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_2"/> then
/// this setting will have the value <c>200</c> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// earlier then this setting will have the value <see langword="null"/> unless explicitly configured.
/// </para>
/// </summary>
public int? MaxValidationDepth
{
get => _maxValidationDepth.Value;
set
{
if (value != null && value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_maxValidationDepth.Value = value;
}
}
/// <summary>
/// Gets or sets a value that determines if <see cref="ValidationVisitor"/>
/// can short-circuit validation when a model does not have any associated validators.
/// </summary>
/// <value>
/// The default value is <see langword="true"/> if the version is
/// <see cref="CompatibilityVersion.Version_2_2"/> or later; <see langword="false"/> otherwise.
/// </value>
/// <remarks>
/// When <see cref="ModelMetadata.HasValidators"/> is <see langword="true"/>, that is, it is determined
/// that a model or any of it's properties or collection elements cannot have any validators,
/// <see cref="ValidationVisitor"/> can short-circuit validation for the model and mark the object
/// graph as valid. Setting this property to <see langword="true"/>, allows <see cref="ValidationVisitor"/> to
/// perform this optimization.
/// <para>
/// This property is associated with a compatibility switch and can provide a different behavior depending on
/// the configured compatibility version for the application. See <see cref="CompatibilityVersion"/> for
/// guidance and examples of setting the application's compatibility version.
/// </para>
/// <para>
/// Configuring the desired value of the compatibility switch by calling this property's setter will take precedence
/// over the value implied by the application's <see cref="CompatibilityVersion"/>.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_2"/> then
/// this setting will have the value <see langword="true"/> unless explicitly configured.
/// </para>
/// <para>
/// If the application's compatibility version is set to <see cref="CompatibilityVersion.Version_2_1"/> or
/// earlier then this setting will have the value <see langword="false"/> unless explicitly configured.
/// </para>
/// </remarks>
public bool AllowShortCircuitingValidationWhenNoValidatorsArePresent
{
get => _allowShortCircuitingValidationWhenNoValidatorsArePresent.Value;
set => _allowShortCircuitingValidationWhenNoValidatorsArePresent.Value = value;
}
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator()
{
return ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
}
}