Correct StyleCop violations

- StyleCop working again (handles C# 6.0 additions) though only locally for me
- disable some new rules:
 - ConstFieldNamesMustBeginWithUpperCaseLetter
 - InstanceReadonlyElementsMustAppearBeforeInstanceNonReadonlyElements
 - StaticReadonlyElementsMustAppearBeforeStaticNonReadonlyElements
 - StaticReadonlyFieldsMustBeginWithUpperCaseLetter
 - PrefixCallsCorrectly
- correct remaining violations
 - lots of long lines for example
 - use more `var`; some manual updates since StyleCop doesn't check seemingly-unused blocks

nit: remove new trailing whitespace (was paranoid about adding it w/ fixes)
This commit is contained in:
Doug Bunting 2015-01-06 16:11:32 -08:00
parent 227f564098
commit 6df288bce7
90 changed files with 674 additions and 444 deletions

View File

@ -12,6 +12,11 @@
<Analyzers> <Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.NamingRules"> <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
<Rules> <Rules>
<Rule Name="ConstFieldNamesMustBeginWithUpperCaseLetter">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="FieldNamesMustNotBeginWithUnderscore"> <Rule Name="FieldNamesMustNotBeginWithUnderscore">
<RuleSettings> <RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
@ -22,6 +27,11 @@
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings> </RuleSettings>
</Rule> </Rule>
<Rule Name="StaticReadonlyFieldsMustBeginWithUpperCaseLetter">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules> </Rules>
<AnalyzerSettings> <AnalyzerSettings>
<CollectionProperty Name="Hungarian"> <CollectionProperty Name="Hungarian">
@ -274,6 +284,11 @@
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings> </RuleSettings>
</Rule> </Rule>
<Rule Name="PrefixCallsCorrectly">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="PrefixLocalCallsWithThis"> <Rule Name="PrefixLocalCallsWithThis">
<RuleSettings> <RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
@ -384,11 +399,21 @@
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings> </RuleSettings>
</Rule> </Rule>
<Rule Name="InstanceReadonlyElementsMustAppearBeforeInstanceNonReadonlyElements">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
<Rule Name="StaticElementsMustAppearBeforeInstanceElements"> <Rule Name="StaticElementsMustAppearBeforeInstanceElements">
<RuleSettings> <RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings> </RuleSettings>
</Rule> </Rule>
<Rule Name="StaticReadonlyElementsMustAppearBeforeStaticNonReadonlyElements">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules> </Rules>
<AnalyzerSettings /> <AnalyzerSettings />
</Analyzer> </Analyzer>
@ -399,7 +424,7 @@
<BooleanProperty Name="Enabled">False</BooleanProperty> <BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings> </RuleSettings>
</Rule> </Rule>
<!-- Creates a lot of noise with anonymous objects --> <!-- Creates a lot of noise with anonymous objects -->
<Rule Name="OpeningCurlyBracketsMustBeSpacedCorrectly"> <Rule Name="OpeningCurlyBracketsMustBeSpacedCorrectly">
<RuleSettings> <RuleSettings>

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc
return false; return false;
} }
for (int idx = 0; idx < t1.Length; ++idx) for (var idx = 0; idx < t1.Length; ++idx)
{ {
if (t1[idx] != t2[idx]) if (t1[idx] != t2[idx])
{ {

View File

@ -119,7 +119,6 @@ namespace Microsoft.AspNet.Mvc
throw new FileNotFoundException(message, path); throw new FileNotFoundException(message, path);
} }
// Internal for unit testing purposes only
/// <summary> /// <summary>
/// Creates a normalized representation of the given <paramref name="path"/>. The default /// Creates a normalized representation of the given <paramref name="path"/>. The default
/// implementation doesn't support files with '\' in the file name and treats the '\' as /// implementation doesn't support files with '\' in the file name and treats the '\' as
@ -128,6 +127,7 @@ namespace Microsoft.AspNet.Mvc
/// </summary> /// </summary>
/// <param name="path">The path to normalize.</param> /// <param name="path">The path to normalize.</param>
/// <returns>The normalized path.</returns> /// <returns>The normalized path.</returns>
// Internal for unit testing purposes only
protected internal virtual string NormalizePath([NotNull] string path) protected internal virtual string NormalizePath([NotNull] string path)
{ {
// Unix systems support '\' as part of the file name. So '\' is not // Unix systems support '\' as part of the file name. So '\' is not
@ -153,13 +153,13 @@ namespace Microsoft.AspNet.Mvc
return path.Replace('\\', '/'); return path.Replace('\\', '/');
} }
// Internal for unit testing purposes only
/// <summary> /// <summary>
/// Determines if the provided path is absolute or relative. The default implementation considers /// Determines if the provided path is absolute or relative. The default implementation considers
/// paths starting with '/' to be relative. /// paths starting with '/' to be relative.
/// </summary> /// </summary>
/// <param name="path">The path to examine.</param> /// <param name="path">The path to examine.</param>
/// <returns>True if the path is absolute.</returns> /// <returns>True if the path is absolute.</returns>
// Internal for unit testing purposes only
protected internal virtual bool IsPathRooted([NotNull] string path) protected internal virtual bool IsPathRooted([NotNull] string path)
{ {
// We consider paths to be rooted if they start with '<<VolumeLetter>>:' and do // We consider paths to be rooted if they start with '<<VolumeLetter>>:' and do

View File

@ -84,7 +84,7 @@ namespace Microsoft.AspNet.Mvc
{ {
builder.Append('%'); builder.Append('%');
int i = b; var i = b;
AddHexDigitToStringBuilder(i >> 4, builder); AddHexDigitToStringBuilder(i >> 4, builder);
AddHexDigitToStringBuilder(i % 16, builder); AddHexDigitToStringBuilder(i % 16, builder);
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
internal sealed class AntiForgeryToken internal sealed class AntiForgeryToken

View File

@ -23,7 +23,8 @@ namespace Microsoft.AspNet.Mvc
public AntiForgeryToken GetCookieToken(HttpContext httpContext) public AntiForgeryToken GetCookieToken(HttpContext httpContext)
{ {
var contextAccessor = httpContext.RequestServices.GetRequiredService<IContextAccessor<AntiForgeryContext>>(); var contextAccessor =
httpContext.RequestServices.GetRequiredService<IContextAccessor<AntiForgeryContext>>();
if (contextAccessor.Value != null) if (contextAccessor.Value != null)
{ {
return contextAccessor.Value.CookieToken; return contextAccessor.Value.CookieToken;
@ -56,7 +57,8 @@ namespace Microsoft.AspNet.Mvc
{ {
// Add the cookie to the request based context. // Add the cookie to the request based context.
// This is useful if the cookie needs to be reloaded in the context of the same request. // This is useful if the cookie needs to be reloaded in the context of the same request.
var contextAccessor = httpContext.RequestServices.GetRequiredService<IContextAccessor<AntiForgeryContext>>(); var contextAccessor =
httpContext.RequestServices.GetRequiredService<IContextAccessor<AntiForgeryContext>>();
Debug.Assert(contextAccessor.Value == null, "AntiForgeryContext should be set only once per request."); Debug.Assert(contextAccessor.Value == null, "AntiForgeryContext should be set only once per request.");
contextAccessor.SetValue(new AntiForgeryContext() { CookieToken = token }); contextAccessor.SetValue(new AntiForgeryContext() { CookieToken = token });

View File

@ -233,7 +233,6 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0] == methodInfo); typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0] == methodInfo);
} }
/// <summary> /// <summary>
/// Creates an <see cref="ActionModel"/> for the given <see cref="MethodInfo"/>. /// Creates an <see cref="ActionModel"/> for the given <see cref="MethodInfo"/>.
/// </summary> /// </summary>

View File

@ -67,9 +67,8 @@ namespace Microsoft.AspNet.Mvc
{ {
if (_viewEngine == null) if (_viewEngine == null)
{ {
_viewEngine = ActionContext?. _viewEngine =
HttpContext?. ActionContext?.HttpContext?.RequestServices.GetRequiredService<ICompositeViewEngine>();
RequestServices.GetRequiredService<ICompositeViewEngine>();
} }
return _viewEngine; return _viewEngine;
@ -797,7 +796,7 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current /// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/>. /// <see cref="IValueProvider"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
@ -811,7 +810,7 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current /// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>. /// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
@ -826,7 +825,7 @@ namespace Microsoft.AspNet.Mvc
{ {
if (BindingContextProvider == null) if (BindingContextProvider == null)
{ {
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider), var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
GetType().FullName); GetType().FullName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
@ -836,7 +835,7 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a /// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>. /// <paramref name="prefix"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
@ -853,7 +852,7 @@ namespace Microsoft.AspNet.Mvc
{ {
if (BindingContextProvider == null) if (BindingContextProvider == null)
{ {
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider), var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
GetType().FullName); GetType().FullName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
@ -870,14 +869,14 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current /// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>. /// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
/// <param name="model">The model instance to update.</param> /// <param name="model">The model instance to update.</param>
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>. /// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
/// </param> /// </param>
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties /// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
/// which need to be included for the current model.</param> /// which need to be included for the current model.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns> /// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
[NonAction] [NonAction]
@ -907,7 +906,7 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using values from the controller's current /// Updates the specified <paramref name="model"/> instance using values from the controller's current
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>. /// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
@ -925,7 +924,7 @@ namespace Microsoft.AspNet.Mvc
{ {
if (BindingContextProvider == null) if (BindingContextProvider == null)
{ {
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider), var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
GetType().FullName); GetType().FullName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
@ -943,7 +942,7 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a /// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>. /// <paramref name="prefix"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
@ -951,7 +950,7 @@ namespace Microsoft.AspNet.Mvc
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/> /// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>
/// </param> /// </param>
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param> /// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties /// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
/// which need to be included for the current model.</param> /// which need to be included for the current model.</param>
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns> /// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
[NonAction] [NonAction]
@ -964,7 +963,7 @@ namespace Microsoft.AspNet.Mvc
{ {
if (BindingContextProvider == null) if (BindingContextProvider == null)
{ {
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider), var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
GetType().FullName); GetType().FullName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }
@ -982,7 +981,7 @@ namespace Microsoft.AspNet.Mvc
} }
/// <summary> /// <summary>
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a /// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
/// <paramref name="prefix"/>. /// <paramref name="prefix"/>.
/// </summary> /// </summary>
/// <typeparam name="TModel">The type of the model object.</typeparam> /// <typeparam name="TModel">The type of the model object.</typeparam>
@ -1002,7 +1001,7 @@ namespace Microsoft.AspNet.Mvc
{ {
if (BindingContextProvider == null) if (BindingContextProvider == null)
{ {
var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider), var message = Resources.FormatPropertyOfTypeCannotBeNull(nameof(BindingContextProvider),
GetType().FullName); GetType().FullName);
throw new InvalidOperationException(message); throw new InvalidOperationException(message);
} }

View File

@ -5,8 +5,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Mvc.ApplicationModels; using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;

View File

@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Mvc
public class DefaultAssemblyProvider : IAssemblyProvider public class DefaultAssemblyProvider : IAssemblyProvider
{ {
/// <summary> /// <summary>
/// Gets the set of assembly names that are used as root for discovery of /// Gets the set of assembly names that are used as root for discovery of
/// MVC controllers, view components and views. /// MVC controllers, view components and views.
/// </summary> /// </summary>
protected virtual HashSet<string> ReferenceAssemblies { get; } = new HashSet<string>(StringComparer.Ordinal) protected virtual HashSet<string> ReferenceAssemblies { get; } = new HashSet<string>(StringComparer.Ordinal)
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
/// <summary> /// <summary>
/// Returns a list of libraries that references the assemblies in <see cref="ReferenceAssemblies"/>. /// Returns a list of libraries that references the assemblies in <see cref="ReferenceAssemblies"/>.
/// By default it returns all assemblies that reference any of the primary MVC assemblies /// By default it returns all assemblies that reference any of the primary MVC assemblies
/// while ignoring MVC assemblies. /// while ignoring MVC assemblies.
/// </summary> /// </summary>
/// <returns>A set of <see cref="ILibraryInformation"/>.</returns> /// <returns>A set of <see cref="ILibraryInformation"/>.</returns>

View File

@ -87,7 +87,8 @@ namespace Microsoft.AspNet.Mvc
foreach (var parameter in parameterMetadata) foreach (var parameter in parameterMetadata)
{ {
var parameterType = parameter.ModelType; var parameterType = parameter.ModelType;
var modelBindingContext = GetModelBindingContext(parameter, actionBindingContext, operationBindingContext); var modelBindingContext =
GetModelBindingContext(parameter, actionBindingContext, operationBindingContext);
if (await actionBindingContext.ModelBinder.BindModelAsync(modelBindingContext)) if (await actionBindingContext.ModelBinder.BindModelAsync(modelBindingContext))
{ {
arguments[parameter.PropertyName] = modelBindingContext.Model; arguments[parameter.PropertyName] = modelBindingContext.Model;

View File

@ -17,7 +17,8 @@ namespace Microsoft.AspNet.Mvc
public class DefaultPropertyBindingPredicateProvider<TModel> : IPropertyBindingPredicateProvider public class DefaultPropertyBindingPredicateProvider<TModel> : IPropertyBindingPredicateProvider
where TModel : class where TModel : class
{ {
private static readonly Func<ModelBindingContext, string, bool> _defaultFilter = (context, propertyName) => true; private static readonly Func<ModelBindingContext, string, bool> _defaultFilter =
(context, propertyName) => true;
/// <summary> /// <summary>
/// The prefix which is used while generating the property filter. /// The prefix which is used while generating the property filter.
@ -57,7 +58,8 @@ namespace Microsoft.AspNet.Mvc
} }
} }
private Func<ModelBindingContext, string, bool> GetPredicateFromExpression(IEnumerable<Expression<Func<TModel, object>>> includeExpressions) private Func<ModelBindingContext, string, bool> GetPredicateFromExpression(
IEnumerable<Expression<Func<TModel, object>>> includeExpressions)
{ {
var expression = ModelBindingHelper.GetIncludePredicateExpression(Prefix, includeExpressions.ToArray()); var expression = ModelBindingHelper.GetIncludePredicateExpression(Prefix, includeExpressions.ToArray());
return expression.Compile(); return expression.Compile();

View File

@ -45,7 +45,6 @@ namespace Microsoft.AspNet.Mvc.Description
get { return DefaultOrder.DefaultFrameworkSortOrder; } get { return DefaultOrder.DefaultFrameworkSortOrder; }
} }
/// <inheritdoc /> /// <inheritdoc />
public void Invoke(ApiDescriptionProviderContext context, Action callNext) public void Invoke(ApiDescriptionProviderContext context, Action callNext)
{ {
@ -157,7 +156,8 @@ namespace Microsoft.AspNet.Mvc.Description
// Process parameters that only appear on the path template if any. // Process parameters that only appear on the path template if any.
foreach (var templateParameter in templateParameters) foreach (var templateParameter in templateParameters)
{ {
var parameterDescription = GetParameter(parameterDescriptor: null, templateParameter: templateParameter); var parameterDescription =
GetParameter(parameterDescriptor: null, templateParameter: templateParameter);
apiDescription.ParameterDescriptions.Add(parameterDescription); apiDescription.ParameterDescriptions.Add(parameterDescription);
} }
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public interface IAuthorizationFilter : IFilter public interface IAuthorizationFilter : IFilter

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public interface IExceptionFilter : IFilter public interface IExceptionFilter : IFilter

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public interface IInputFormatterSelector public interface IInputFormatterSelector

View File

@ -13,8 +13,8 @@ namespace Microsoft.AspNet.Mvc
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class HttpMethodAttribute : Attribute, IActionHttpMethodProvider, IRouteTemplateProvider public abstract class HttpMethodAttribute : Attribute, IActionHttpMethodProvider, IRouteTemplateProvider
{ {
private int? _order;
private readonly IEnumerable<string> _httpMethods; private readonly IEnumerable<string> _httpMethods;
private int? _order;
/// <summary> /// <summary>
/// Creates a new <see cref="HttpMethodAttribute"/> with the given /// Creates a new <see cref="HttpMethodAttribute"/> with the given

View File

@ -32,7 +32,8 @@ namespace Microsoft.AspNet.Mvc.Logging
public Type ActionConstraintMetadataType { get; } public Type ActionConstraintMetadataType { get; }
/// <summary> /// <summary>
/// The constraint order if this is an <see cref="IActionConstraint"/>. See <see cref="IActionConstraint.Order"/>. /// The constraint order if this is an <see cref="IActionConstraint"/>. See
/// <see cref="IActionConstraint.Order"/>.
/// </summary> /// </summary>
public int Order { get; } public int Order { get; }

View File

@ -25,7 +25,8 @@ namespace Microsoft.AspNet.Mvc.Logging
AttributeRouteInfo = new AttributeRouteInfoValues(inner.AttributeRouteInfo); AttributeRouteInfo = new AttributeRouteInfoValues(inner.AttributeRouteInfo);
RouteValueDefaults = inner.RouteValueDefaults.ToDictionary(i => i.Key, i => i.Value.ToString()); RouteValueDefaults = inner.RouteValueDefaults.ToDictionary(i => i.Key, i => i.Value.ToString());
ActionConstraints = inner.ActionConstraints?.Select(a => new ActionConstraintValues(a))?.ToList(); ActionConstraints = inner.ActionConstraints?.Select(a => new ActionConstraintValues(a))?.ToList();
HttpMethods = inner.ActionConstraints?.OfType<HttpMethodConstraint>().SelectMany(c => c.HttpMethods).ToList(); HttpMethods =
inner.ActionConstraints?.OfType<HttpMethodConstraint>().SelectMany(c => c.HttpMethods).ToList();
Properties = inner.Properties.ToDictionary(i => i.Key.ToString(), i => i.Value.GetType()); Properties = inner.Properties.ToDictionary(i => i.Key.ToString(), i => i.Value.GetType());
var controllerActionDescriptor = inner as ControllerActionDescriptor; var controllerActionDescriptor = inner as ControllerActionDescriptor;
if (controllerActionDescriptor != null) if (controllerActionDescriptor != null)

View File

@ -1,8 +1,8 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Framework.Logging;
using Microsoft.AspNet.Mvc.ApplicationModels; using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {

View File

@ -4,8 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.Framework.Logging;
using Microsoft.AspNet.Mvc.ApplicationModels; using Microsoft.AspNet.Mvc.ApplicationModels;
using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Mvc.Logging namespace Microsoft.AspNet.Mvc.Logging
{ {

View File

@ -1,4 +1,7 @@
using System; // Copyright (c) Microsoft Open Technologies, Inc. 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.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;

View File

@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Mvc
if (formatter == null) if (formatter == null)
{ {
var unsupportedContentType = Resources.FormatUnsupportedContentType( var unsupportedContentType = Resources.FormatUnsupportedContentType(
bindingContext.OperationBindingContext.HttpContext.Request.ContentType); bindingContext.OperationBindingContext.HttpContext.Request.ContentType);
bindingContext.ModelState.AddModelError(bindingContext.ModelName, unsupportedContentType); bindingContext.ModelState.AddModelError(bindingContext.ModelName, unsupportedContentType);
// Should always return true so that the model binding process ends here. // Should always return true so that the model binding process ends here.

View File

@ -90,7 +90,7 @@ namespace Microsoft.AspNet.Mvc
where TModel : class where TModel : class
{ {
var includeExpression = GetIncludePredicateExpression(prefix, includeExpressions); var includeExpression = GetIncludePredicateExpression(prefix, includeExpressions);
Func<ModelBindingContext, string, bool> predicate = includeExpression.Compile(); var predicate = includeExpression.Compile();
return TryUpdateModelAsync( return TryUpdateModelAsync(
model, model,

View File

@ -432,7 +432,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
if (defaultValue != null) if (defaultValue != null)
{ {
selectList = UpdateSelectListItemsWithDefaultValue(selectList, defaultValue, allowMultiple, out selectedValues); selectList =
UpdateSelectListItemsWithDefaultValue(selectList, defaultValue, allowMultiple, out selectedValues);
} }
else else
{ {
@ -606,7 +607,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
// Only the style of the span is changed according to the errors if message is null or empty. // Only the style of the span is changed according to the errors if message is null or empty.
// Otherwise the content and style is handled by the client-side validation. // Otherwise the content and style is handled by the client-side validation.
var className = (modelError != null) ? HtmlHelper.ValidationMessageCssClassName : HtmlHelper.ValidationMessageValidCssClassName; var className = (modelError != null) ?
HtmlHelper.ValidationMessageCssClassName :
HtmlHelper.ValidationMessageValidCssClassName;
tagBuilder.AddCssClass(className); tagBuilder.AddCssClass(className);
if (!string.IsNullOrEmpty(message)) if (!string.IsNullOrEmpty(message))

View File

@ -702,7 +702,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
return CreateForm(); return CreateForm();
} }
protected virtual HtmlString GenerateHidden( protected virtual HtmlString GenerateHidden(
ModelMetadata metadata, ModelMetadata metadata,
string name, string name,

View File

@ -237,8 +237,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
case '-': case '-':
case '_': case '_':
case ':': case ':':
// Note '.' is valid according to the HTML 4.01 specification. Disallowed here to avoid confusion // Note '.' is valid according to the HTML 4.01 specification. Disallowed here to avoid
// with CSS class selectors or when using jQuery. // confusion with CSS class selectors or when using jQuery.
return true; return true;
default: default:

View File

@ -20,12 +20,12 @@ namespace Microsoft.AspNet.Mvc.Routing
public class AttributeRoute : IRouter public class AttributeRoute : IRouter
{ {
private readonly IRouter _next; private readonly IRouter _next;
private readonly LinkGenerationDecisionTree _linkGenerationTree;
private readonly TemplateRoute[] _matchingRoutes; private readonly TemplateRoute[] _matchingRoutes;
private readonly IDictionary<string, AttributeRouteLinkGenerationEntry> _namedEntries; private readonly IDictionary<string, AttributeRouteLinkGenerationEntry> _namedEntries;
private ILogger _logger; private ILogger _logger;
private ILogger _constraintLogger; private ILogger _constraintLogger;
private readonly LinkGenerationDecisionTree _linkGenerationTree;
/// <summary> /// <summary>
/// Creates a new <see cref="AttributeRoute"/>. /// Creates a new <see cref="AttributeRoute"/>.

View File

@ -22,7 +22,8 @@ namespace Microsoft.AspNet.Mvc
private readonly IActionSelector _actionSelector; private readonly IActionSelector _actionSelector;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UrlHelper"/> class using the specified action context and action selector. /// Initializes a new instance of the <see cref="UrlHelper"/> class using the specified action context and
/// action selector.
/// </summary> /// </summary>
/// <param name="contextAccessor">The <see cref="IContextAccessor{TContext}"/> to access the action context /// <param name="contextAccessor">The <see cref="IContextAccessor{TContext}"/> to access the action context
/// of the current request.</param> /// of the current request.</param>

View File

@ -13,10 +13,10 @@ namespace Microsoft.AspNet.Mvc
/// <remarks> /// <remarks>
/// <see cref="ContentViewComponentResult"/> always writes HTML encoded text from the /// <see cref="ContentViewComponentResult"/> always writes HTML encoded text from the
/// <see cref="EncodedContent"/> property. /// <see cref="EncodedContent"/> property.
/// ///
/// When using <see cref="ContentViewComponentResult(string)"/>, the provided content will be HTML /// When using <see cref="ContentViewComponentResult(string)"/>, the provided content will be HTML
/// encoded and stored in <see cref="EncodedContent"/>. /// encoded and stored in <see cref="EncodedContent"/>.
/// ///
/// To write pre-encoded conent, use <see cref="ContentViewComponentResult(HtmlString)"/>. /// To write pre-encoded conent, use <see cref="ContentViewComponentResult(HtmlString)"/>.
/// </remarks> /// </remarks>
public class ContentViewComponentResult : IViewComponentResult public class ContentViewComponentResult : IViewComponentResult

View File

@ -8,12 +8,11 @@ namespace Microsoft.AspNet.Mvc
{ {
public class ViewContext : ActionContext public class ViewContext : ActionContext
{ {
private DynamicViewData _viewBag;
// We need a default FormContext if the user uses html <form> instead of an MvcForm // We need a default FormContext if the user uses html <form> instead of an MvcForm
private readonly FormContext _defaultFormContext = new FormContext(); private readonly FormContext _defaultFormContext = new FormContext();
private FormContext _formContext; private FormContext _formContext;
private DynamicViewData _viewBag;
public ViewContext( public ViewContext(
[NotNull] ActionContext actionContext, [NotNull] ActionContext actionContext,

View File

@ -7,7 +7,6 @@ namespace Microsoft.AspNet.Mvc
{ {
public class ViewDataDictionary<TModel> : ViewDataDictionary public class ViewDataDictionary<TModel> : ViewDataDictionary
{ {
// References may not show up due to ITypeActivator use in RazorPageActivator.
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ViewDataDictionary{TModel}"/> class. /// Initializes a new instance of the <see cref="ViewDataDictionary{TModel}"/> class.
/// </summary> /// </summary>
@ -15,6 +14,7 @@ namespace Microsoft.AspNet.Mvc
/// For use when creating a <see cref="ViewDataDictionary{TModel}"/> for a new top-level scope. /// For use when creating a <see cref="ViewDataDictionary{TModel}"/> for a new top-level scope.
/// </remarks> /// </remarks>
/// <inheritdoc /> /// <inheritdoc />
// References may not show up due to ITypeActivator use in RazorPageActivator.
public ViewDataDictionary( public ViewDataDictionary(
[NotNull] IModelMetadataProvider metadataProvider, [NotNull] IModelMetadataProvider metadataProvider,
[NotNull] ModelStateDictionary modelState) [NotNull] ModelStateDictionary modelState)
@ -22,7 +22,6 @@ namespace Microsoft.AspNet.Mvc
{ {
} }
// References may not show up due to ITypeActivator use in RazorPageActivator.
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ViewDataDictionary{TModel}"/> class based in part on an /// Initializes a new instance of the <see cref="ViewDataDictionary{TModel}"/> class based in part on an
/// existing <see cref="ViewDataDictionary"/> instance. /// existing <see cref="ViewDataDictionary"/> instance.
@ -40,14 +39,12 @@ namespace Microsoft.AspNet.Mvc
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <inheritdoc /> /// <inheritdoc />
// References may not show up due to ITypeActivator use in RazorPageActivator.
public ViewDataDictionary([NotNull] ViewDataDictionary source) public ViewDataDictionary([NotNull] ViewDataDictionary source)
: base(source, declaredModelType: typeof(TModel)) : base(source, declaredModelType: typeof(TModel))
{ {
} }
// Model parameter type is object to allow "model: null" calls even when TModel is a value type. A TModel
// parameter would likely require IEquatable<TModel> type restrictions to pass expected null value to the base
// constructor.
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ViewDataDictionary{TModel}"/> class based in part on an /// Initializes a new instance of the <see cref="ViewDataDictionary{TModel}"/> class based in part on an
/// existing <see cref="ViewDataDictionary"/> instance. This constructor is careful to avoid exceptions /// existing <see cref="ViewDataDictionary"/> instance. This constructor is careful to avoid exceptions
@ -64,6 +61,9 @@ namespace Microsoft.AspNet.Mvc
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <inheritdoc /> /// <inheritdoc />
// Model parameter type is object to allow "model: null" calls even when TModel is a value type. A TModel
// parameter would likely require IEquatable<TModel> type restrictions to pass expected null value to the base
// constructor.
public ViewDataDictionary([NotNull] ViewDataDictionary source, object model) public ViewDataDictionary([NotNull] ViewDataDictionary source, object model)
: base(source, model, declaredModelType: typeof(TModel)) : base(source, model, declaredModelType: typeof(TModel))
{ {

View File

@ -14,7 +14,8 @@ namespace Microsoft.AspNet.Mvc
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class BindAttribute : Attribute, IModelNameProvider, IPropertyBindingPredicateProvider public class BindAttribute : Attribute, IModelNameProvider, IPropertyBindingPredicateProvider
{ {
private static readonly Func<ModelBindingContext, string, bool> _defaultFilter = (context, propertyName) => true; private static readonly Func<ModelBindingContext, string, bool> _defaultFilter =
(context, propertyName) => true;
private Func<ModelBindingContext, string, bool> _predicateFromInclude; private Func<ModelBindingContext, string, bool> _predicateFromInclude;

View File

@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var rawValueArray = RawValueToObjectArray(rawValue); var rawValueArray = RawValueToObjectArray(rawValue);
foreach (var rawValueElement in rawValueArray) foreach (var rawValueElement in rawValueArray)
{ {
var innerModelMetadata = var innerModelMetadata =
bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(null, typeof(TElement)); bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(null, typeof(TElement));
var innerBindingContext = new ModelBindingContext(bindingContext, var innerBindingContext = new ModelBindingContext(bindingContext,
bindingContext.ModelName, bindingContext.ModelName,
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
foreach (var indexName in indexNames) foreach (var indexName in indexNames)
{ {
var fullChildName = ModelBindingHelper.CreateIndexModelName(bindingContext.ModelName, indexName); var fullChildName = ModelBindingHelper.CreateIndexModelName(bindingContext.ModelName, indexName);
var childModelMetadata = var childModelMetadata =
bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(null, typeof(TElement)); bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(null, typeof(TElement));
var childBindingContext = new ModelBindingContext(bindingContext, fullChildName, childModelMetadata); var childBindingContext = new ModelBindingContext(bindingContext, fullChildName, childModelMetadata);

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var propertyModelName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, var propertyModelName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName,
propertyMetadata.PropertyName); propertyMetadata.PropertyName);
var propertyBindingContext = new ModelBindingContext(bindingContext, var propertyBindingContext = new ModelBindingContext(bindingContext,
propertyModelName, propertyModelName,
propertyMetadata); propertyMetadata);

View File

@ -80,16 +80,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName); bindingContext.ModelName);
} }
var validationContext = new ModelValidationContext(bindingContext.OperationBindingContext.MetadataProvider, var validationContext = new ModelValidationContext(
bindingContext.OperationBindingContext.ValidatorProvider, bindingContext.OperationBindingContext.MetadataProvider,
bindingContext.ModelState, bindingContext.OperationBindingContext.ValidatorProvider,
bindingContext.ModelMetadata, bindingContext.ModelState,
containerMetadata: null); bindingContext.ModelMetadata,
containerMetadata: null);
newBindingContext.ValidationNode.Validate(validationContext, parentNode: null); newBindingContext.ValidationNode.Validate(validationContext, parentNode: null);
} }
bindingContext.OperationBindingContext.BodyBindingState = bindingContext.OperationBindingContext.BodyBindingState =
newBindingContext.OperationBindingContext.BodyBindingState; newBindingContext.OperationBindingContext.BodyBindingState;
bindingContext.Model = newBindingContext.Model; bindingContext.Model = newBindingContext.Model;
return true; return true;
@ -147,13 +148,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var metadata = oldBindingContext.ModelMetadata.BinderMetadata as IValueProviderMetadata; var metadata = oldBindingContext.ModelMetadata.BinderMetadata as IValueProviderMetadata;
if (metadata != null) if (metadata != null)
{ {
// ValueProvider property might contain a filtered list of value providers. // ValueProvider property might contain a filtered list of value providers.
// While deciding to bind a particular property which is annotated with a IValueProviderMetadata, // While deciding to bind a particular property which is annotated with a IValueProviderMetadata,
// instead of refiltering an already filtered list, we need to filter value providers from a global list // instead of refiltering an already filtered list, we need to filter value providers from a global
// of all value providers. This is so that every artifact that is explicitly marked using an // list of all value providers. This is so that every artifact that is explicitly marked using an
// IValueProviderMetadata can restrict model binding to only use value providers which support this // IValueProviderMetadata can restrict model binding to only use value providers which support this
// IValueProviderMetadata. // IValueProviderMetadata.
var valueProvider = oldBindingContext.OperationBindingContext.ValueProvider as IMetadataAwareValueProvider; var valueProvider =
oldBindingContext.OperationBindingContext.ValueProvider as IMetadataAwareValueProvider;
if (valueProvider != null) if (valueProvider != null)
{ {
newBindingContext.ValueProvider = valueProvider.Filter(metadata); newBindingContext.ValueProvider = valueProvider.Filter(metadata);
@ -171,7 +173,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var currentModelNeedsToReadBody = newIsFormatterBasedMetadataFound || newIsFormBasedMetadataFound; var currentModelNeedsToReadBody = newIsFormatterBasedMetadataFound || newIsFormBasedMetadataFound;
var oldState = oldBindingContext.OperationBindingContext.BodyBindingState; var oldState = oldBindingContext.OperationBindingContext.BodyBindingState;
// We need to throw if there are multiple models which can cause body to be read multiple times. // We need to throw if there are multiple models which can cause body to be read multiple times.
// Reading form data multiple times is ok since we cache form data. For the models marked to read using // Reading form data multiple times is ok since we cache form data. For the models marked to read using
// formatters, multiple reads are not allowed. // formatters, multiple reads are not allowed.
if (oldState == BodyBindingState.FormatterBased && currentModelNeedsToReadBody || if (oldState == BodyBindingState.FormatterBased && currentModelNeedsToReadBody ||
@ -179,7 +181,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
throw new InvalidOperationException(Resources.MultipleBodyParametersOrPropertiesAreNotAllowed); throw new InvalidOperationException(Resources.MultipleBodyParametersOrPropertiesAreNotAllowed);
} }
var state = oldBindingContext.OperationBindingContext.BodyBindingState; var state = oldBindingContext.OperationBindingContext.BodyBindingState;
if (newIsFormatterBasedMetadataFound) if (newIsFormatterBasedMetadataFound)
{ {
@ -187,7 +189,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
} }
else if (newIsFormBasedMetadataFound && oldState != BodyBindingState.FormatterBased) else if (newIsFormBasedMetadataFound && oldState != BodyBindingState.FormatterBased)
{ {
// Only update the model binding state if we have not discovered formatter based state already. // Only update the model binding state if we have not discovered formatter based state already.
state = BodyBindingState.FormBased; state = BodyBindingState.FormBased;
} }

View File

@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var binder = (IModelBinder)_activator.CreateInstance(_serviceProvider, binderType); var binder = (IModelBinder)_activator.CreateInstance(_serviceProvider, binderType);
await binder.BindModelAsync(bindingContext); await binder.BindModelAsync(bindingContext);
// Was able to resolve a binder type, hence we should tell the model binding system to return // Was able to resolve a binder type, hence we should tell the model binding system to return
// true so that none of the other model binders participate. // true so that none of the other model binders participate.
return true; return true;
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
/// <summary> /// <summary>

View File

@ -28,12 +28,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
internal async Task<BindResult<TModel>> TryBindStrongModel<TModel>(ModelBindingContext parentBindingContext, internal async Task<BindResult<TModel>> TryBindStrongModel<TModel>(ModelBindingContext parentBindingContext,
string propertyName) string propertyName)
{ {
var propertyModelMetadata = var propertyModelMetadata =
parentBindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(modelAccessor: null, parentBindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(modelAccessor: null,
modelType: typeof(TModel)); modelType: typeof(TModel));
var propertyModelName = var propertyModelName =
ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName); ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName);
var propertyBindingContext = var propertyBindingContext =
new ModelBindingContext(parentBindingContext, propertyModelName, propertyModelMetadata); new ModelBindingContext(parentBindingContext, propertyModelName, propertyModelMetadata);
if (await propertyBindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyBindingContext)) if (await propertyBindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyBindingContext))

View File

@ -220,7 +220,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var complexModelDtoMetadata = var complexModelDtoMetadata =
bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(() => originalDto, bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(() => originalDto,
typeof(ComplexModelDto)); typeof(ComplexModelDto));
var dtoBindingContext = var dtoBindingContext =
new ModelBindingContext(bindingContext, bindingContext.ModelName, complexModelDtoMetadata); new ModelBindingContext(bindingContext, bindingContext.ModelName, complexModelDtoMetadata);
await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(dtoBindingContext); await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(dtoBindingContext);

View File

@ -11,7 +11,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
IEnumerable<ModelMetadata> GetMetadataForProperties(object container, [NotNull] Type containerType); IEnumerable<ModelMetadata> GetMetadataForProperties(object container, [NotNull] Type containerType);
ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, [NotNull] Type containerType, [NotNull] string propertyName); ModelMetadata GetMetadataForProperty(
Func<object> modelAccessor,
[NotNull] Type containerType,
[NotNull] string propertyName);
ModelMetadata GetMetadataForType(Func<object> modelAccessor, [NotNull] Type modelType); ModelMetadata GetMetadataForType(Func<object> modelAccessor, [NotNull] Type modelType);

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
@ -13,7 +12,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </summary> /// </summary>
public class ModelBindingContext public class ModelBindingContext
{ {
private static readonly Func<ModelBindingContext, string, bool> private static readonly Func<ModelBindingContext, string, bool>
_defaultPropertyFilter = (context, propertyName) => true; _defaultPropertyFilter = (context, propertyName) => true;
private string _modelName; private string _modelName;
@ -53,7 +52,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
} }
/// <summary> /// <summary>
/// Represents the <see cref="OperationBindingContext"/> associated with this context. /// Represents the <see cref="OperationBindingContext"/> associated with this context.
/// </summary> /// </summary>
public OperationBindingContext OperationBindingContext { get; set; } public OperationBindingContext OperationBindingContext { get; set; }

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class ClientModelValidationContext public class ClientModelValidationContext

View File

@ -22,13 +22,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// A factory for validators based on ValidationAttribute. // A factory for validators based on ValidationAttribute.
internal delegate IModelValidator DataAnnotationsModelValidationFactory(ValidationAttribute attribute); internal delegate IModelValidator DataAnnotationsModelValidationFactory(ValidationAttribute attribute);
// A factory for validators based on IValidatableObject
private delegate IModelValidator DataAnnotationsValidatableObjectAdapterFactory();
private static bool _addImplicitRequiredAttributeForValueTypes = true;
private readonly Dictionary<Type, DataAnnotationsModelValidationFactory> _attributeFactories =
BuildAttributeFactoriesDictionary();
// Factories for validation attributes // Factories for validation attributes
private static readonly DataAnnotationsModelValidationFactory _defaultAttributeFactory = private static readonly DataAnnotationsModelValidationFactory _defaultAttributeFactory =
(attribute) => new DataAnnotationsModelValidator(attribute); (attribute) => new DataAnnotationsModelValidator(attribute);
@ -37,6 +30,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private static readonly DataAnnotationsValidatableObjectAdapterFactory _defaultValidatableFactory = private static readonly DataAnnotationsValidatableObjectAdapterFactory _defaultValidatableFactory =
() => new ValidatableObjectAdapter(); () => new ValidatableObjectAdapter();
private static bool _addImplicitRequiredAttributeForValueTypes = true;
private readonly Dictionary<Type, DataAnnotationsModelValidationFactory> _attributeFactories =
BuildAttributeFactoriesDictionary();
// A factory for validators based on IValidatableObject
private delegate IModelValidator DataAnnotationsValidatableObjectAdapterFactory();
internal Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories internal Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories
{ {
get { return _attributeFactories; } get { return _attributeFactories; }

View File

@ -56,7 +56,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// We don't need to recursively traverse the graph for types that shouldn't be validated // We don't need to recursively traverse the graph for types that shouldn't be validated
var modelType = metadata.Model.GetType(); var modelType = metadata.Model.GetType();
if (IsTypeExcludedFromValidation(validationContext.ModelValidationContext.ExcludeFromValidationFilters, modelType)) if (IsTypeExcludedFromValidation(
validationContext.ModelValidationContext.ExcludeFromValidationFilters,
modelType))
{ {
return ShallowValidate(metadata, validationContext, validators); return ShallowValidate(metadata, validationContext, validators);
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class ModelClientValidationRegexRule : ModelClientValidationRule public class ModelClientValidationRegexRule : ModelClientValidationRule

View File

@ -104,7 +104,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
if (SuppressValidation || !validationContext.ModelState.CanAddErrors) if (SuppressValidation || !validationContext.ModelState.CanAddErrors)
{ {
// Short circuit if validation does not need to be applied or if we've reached the max number of validation errors. // Short circuit if validation does not need to be applied or if we've reached the max number of
// validation errors.
return; return;
} }

View File

@ -12,7 +12,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// <summary> /// <summary>
/// Represents a <see cref="IValueProvider"/> whose values come from a collection of <see cref="IValueProvider"/>s. /// Represents a <see cref="IValueProvider"/> whose values come from a collection of <see cref="IValueProvider"/>s.
/// </summary> /// </summary>
public class CompositeValueProvider : Collection<IValueProvider>, IEnumerableValueProvider, IMetadataAwareValueProvider public class CompositeValueProvider
: Collection<IValueProvider>, IEnumerableValueProvider, IMetadataAwareValueProvider
{ {
/// <summary> /// <summary>
/// Initializes a new instance of <see cref="CompositeValueProvider"/>. /// Initializes a new instance of <see cref="CompositeValueProvider"/>.

View File

@ -9,7 +9,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// A <see cref="IMetadataAwareValueProvider"/> value provider which can filter /// A <see cref="IMetadataAwareValueProvider"/> value provider which can filter
/// based on <see cref="IValueProviderMetadata"/>. /// based on <see cref="IValueProviderMetadata"/>.
/// </summary> /// </summary>
/// <typeparam name="TBinderMetadata">Represents a type implementing <see cref="IValueProviderMetadata"/></typeparam> /// <typeparam name="TBinderMetadata">
/// Represents a type implementing <see cref="IValueProviderMetadata"/>
/// </typeparam>
public abstract class MetadataAwareValueProvider<TBinderMetadata> : IMetadataAwareValueProvider public abstract class MetadataAwareValueProvider<TBinderMetadata> : IMetadataAwareValueProvider
where TBinderMetadata : IValueProviderMetadata where TBinderMetadata : IValueProviderMetadata
{ {

View File

@ -16,8 +16,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
where TBinderMetadata : IValueProviderMetadata where TBinderMetadata : IValueProviderMetadata
{ {
private readonly CultureInfo _culture; private readonly CultureInfo _culture;
private PrefixContainer _prefixContainer;
private readonly Func<Task<IReadableStringCollection>> _valuesFactory; private readonly Func<Task<IReadableStringCollection>> _valuesFactory;
private PrefixContainer _prefixContainer;
private IReadableStringCollection _values; private IReadableStringCollection _values;
/// <summary> /// <summary>

View File

@ -15,8 +15,12 @@ namespace Microsoft.AspNet.Mvc.Razor
/// Parses the <see cref="ICompilerOptions"/> for the current executing application and returns a /// Parses the <see cref="ICompilerOptions"/> for the current executing application and returns a
/// <see cref="CompilationSettings"/> used for Roslyn compilation. /// <see cref="CompilationSettings"/> used for Roslyn compilation.
/// </summary> /// </summary>
/// <param name="compilerOptionsProvider">A <see cref="ICompilerOptionsProvider"/> that reads compiler options.</param> /// <param name="compilerOptionsProvider">
/// <param name="applicationEnvironment">The <see cref="IApplicationEnvironment"/> for the executing application.</param> /// A <see cref="ICompilerOptionsProvider"/> that reads compiler options.
/// </param>
/// <param name="applicationEnvironment">
/// The <see cref="IApplicationEnvironment"/> for the executing application.
/// </param>
/// <returns>The <see cref="CompilationSettings"/> for the current application.</returns> /// <returns>The <see cref="CompilationSettings"/> for the current application.</returns>
public static CompilationSettings GetCompilationSettings( public static CompilationSettings GetCompilationSettings(
[NotNull] this ICompilerOptionsProvider compilerOptionsProvider, [NotNull] this ICompilerOptionsProvider compilerOptionsProvider,

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNet.Mvc.Razor
/// file system. /// file system.
/// </param> /// </param>
public CompilerCache(IAssemblyProvider provider, IRazorFileSystemCache fileSystem) public CompilerCache(IAssemblyProvider provider, IRazorFileSystemCache fileSystem)
: this (GetFileInfos(provider.CandidateAssemblies), fileSystem) : this(GetFileInfos(provider.CandidateAssemblies), fileSystem)
{ {
} }

View File

@ -65,7 +65,13 @@ namespace Microsoft.AspNet.Mvc.Razor
/// <summary> /// <summary>
/// Gets a flag that indicates if the file is precompiled. /// Gets a flag that indicates if the file is precompiled.
/// </summary> /// </summary>
public bool IsPreCompiled { get { return Hash != null; } } public bool IsPreCompiled
{
get
{
return Hash != null;
}
}
/// <summary> /// <summary>
/// Gets or sets the <see cref="CompilerCacheEntry"/> for the nearest ViewStart that the compiled type /// Gets or sets the <see cref="CompilerCacheEntry"/> for the nearest ViewStart that the compiled type

View File

@ -4,8 +4,8 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Microsoft.AspNet.FileSystems; using Microsoft.AspNet.FileSystems;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.Expiration.Interfaces; using Microsoft.Framework.Expiration.Interfaces;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {

View File

@ -119,8 +119,7 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
var type = assembly.GetExportedTypes() var type = assembly.GetExportedTypes()
.First(t => t.Name. .First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));
StartsWith(_classPrefix, StringComparison.Ordinal));
return UncachedCompilationResult.Successful(type, compilationContent); return UncachedCompilationResult.Successful(type, compilationContent);
} }

View File

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.Framework.Runtime
{
[AssemblyNeutral]
public interface IBeforeCompileContext
{
CSharpCompilation CSharpCompilation { get; set; }
IList<ResourceDescription> Resources { get; }
IList<Diagnostic> Diagnostics { get; }
}
}

View File

@ -24,9 +24,9 @@ namespace Microsoft.AspNet.Mvc.Razor
public interface IViewLocationExpander public interface IViewLocationExpander
{ {
/// <summary> /// <summary>
/// Invoked by a <see cref="RazorViewEngine"/> to determine the values that would be consumed by this instance of /// Invoked by a <see cref="RazorViewEngine"/> to determine the values that would be consumed by this instance
/// <see cref="IViewLocationExpander"/>. The calculated values are used to determine if the view location has /// of <see cref="IViewLocationExpander"/>. The calculated values are used to determine if the view location
/// changed since the last time it was located. /// has changed since the last time it was located.
/// </summary> /// </summary>
/// <param name="context">The <see cref="ViewLocationExpanderContext"/> for the current view location /// <param name="context">The <see cref="ViewLocationExpanderContext"/> for the current view location
/// expansion operation.</param> /// expansion operation.</param>

View File

@ -11,12 +11,13 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
public static Diagnostic ToDiagnostics([NotNull] this RazorError error, [NotNull] string filePath) public static Diagnostic ToDiagnostics([NotNull] this RazorError error, [NotNull] string filePath)
{ {
var descriptor = new DiagnosticDescriptor(id: "Razor", var descriptor = new DiagnosticDescriptor(
title: "Razor parsing error", id: "Razor",
messageFormat: error.Message.Replace("{", "{{").Replace("}", "}}"), title: "Razor parsing error",
category: "Razor.Parser", messageFormat: error.Message.Replace("{", "{{").Replace("}", "}}"),
defaultSeverity: DiagnosticSeverity.Error, category: "Razor.Parser",
isEnabledByDefault: true); defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
var textSpan = new TextSpan(error.Location.AbsoluteIndex, error.Length); var textSpan = new TextSpan(error.Location.AbsoluteIndex, error.Length);
var linePositionStart = new LinePosition(error.Location.LineIndex, error.Location.CharacterIndex); var linePositionStart = new LinePosition(error.Location.LineIndex, error.Location.CharacterIndex);

View File

@ -43,7 +43,6 @@ namespace Microsoft.AspNet.Mvc.Razor
return syntaxTree; return syntaxTree;
} }
protected virtual string GenerateFile([NotNull] RazorFileInfo fileInfo) protected virtual string GenerateFile([NotNull] RazorFileInfo fileInfo)
{ {
return string.Format(FileFormat, return string.Format(FileFormat,

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Microsoft.AspNet.FileSystems; using Microsoft.AspNet.FileSystems;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
@ -79,7 +78,7 @@ namespace Microsoft.AspNet.Mvc.Razor
private IEnumerable<RelativeFileInfo> GetFileInfosRecursive(string currentPath) private IEnumerable<RelativeFileInfo> GetFileInfosRecursive(string currentPath)
{ {
string path = currentPath; var path = currentPath;
var fileInfos = _fileSystem.GetDirectoryContents(path); var fileInfos = _fileSystem.GetDirectoryContents(path);
if (!fileInfos.Exists) if (!fileInfos.Exists)
@ -152,16 +151,3 @@ namespace Microsoft.AspNet.Mvc.Razor
} }
} }
} }
namespace Microsoft.Framework.Runtime
{
[AssemblyNeutral]
public interface IBeforeCompileContext
{
CSharpCompilation CSharpCompilation { get; set; }
IList<ResourceDescription> Resources { get; }
IList<Diagnostic> Diagnostics { get; }
}
}

View File

@ -122,12 +122,14 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
if (_tagHelperActivator == null) if (_tagHelperActivator == null)
{ {
_tagHelperActivator = ViewContext.HttpContext.RequestServices.GetRequiredService<ITagHelperActivator>(); _tagHelperActivator =
ViewContext.HttpContext.RequestServices.GetRequiredService<ITagHelperActivator>();
} }
return _tagHelperActivator; return _tagHelperActivator;
} }
} }
/// <summary> /// <summary>
/// Creates and activates a <see cref="ITagHelper"/>. /// Creates and activates a <see cref="ITagHelper"/>.
/// </summary> /// </summary>

View File

@ -33,8 +33,7 @@ namespace Microsoft.AspNet.Mvc.Razor
IRazorPageActivator pageActivator, IRazorPageActivator pageActivator,
IViewStartProvider viewStartProvider, IViewStartProvider viewStartProvider,
IRazorPage razorPage, IRazorPage razorPage,
bool isPartial bool isPartial)
)
{ {
_viewEngine = viewEngine; _viewEngine = viewEngine;
_pageActivator = pageActivator; _pageActivator = pageActivator;
@ -53,7 +52,6 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary> /// </summary>
public bool IsPartial { get; } public bool IsPartial { get; }
private bool EnableInstrumentation private bool EnableInstrumentation
{ {
get { return _pageExecutionFeature != null; } get { return _pageExecutionFeature != null; }
@ -97,8 +95,8 @@ namespace Microsoft.AspNet.Mvc.Razor
bool executeViewStart) bool executeViewStart)
{ {
var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding); var razorTextWriter = new RazorTextWriter(context.Writer, context.Writer.Encoding);
TextWriter writer = razorTextWriter; var writer = (TextWriter)razorTextWriter;
IBufferedTextWriter bufferedWriter = razorTextWriter; var bufferedWriter = (IBufferedTextWriter)razorTextWriter;
if (EnableInstrumentation) if (EnableInstrumentation)
{ {

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
/// </exception> /// </exception>
public override void Process(TagHelperContext context, TagHelperOutput output) public override void Process(TagHelperContext context, TagHelperOutput output)
{ {
bool antiForgeryDefault = true; var antiForgeryDefault = true;
var routePrefixedAttributes = output.FindPrefixedAttributes(RouteAttributePrefix); var routePrefixedAttributes = output.FindPrefixedAttributes(RouteAttributePrefix);
// If "action" is already set, it means the user is attempting to use a normal <form>. // If "action" is already set, it means the user is attempting to use a normal <form>.

View File

@ -26,7 +26,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[Activate] [Activate]
protected internal IHtmlGenerator Generator { get; set; } protected internal IHtmlGenerator Generator { get; set; }
// TODO: https://github.com/aspnet/Razor/issues/196 Change to ValidationSummary enum once #196 has been completed.
/// <summary> /// <summary>
/// If <c>All</c> or <c>ModelOnly</c>, appends a validation summary. Acceptable values are defined by the /// If <c>All</c> or <c>ModelOnly</c>, appends a validation summary. Acceptable values are defined by the
/// <see cref="ValidationSummary"/> enum. /// <see cref="ValidationSummary"/> enum.

View File

@ -41,7 +41,8 @@ namespace System.Web.Http
} }
/// <summary> /// <summary>
/// Gets model state after the model binding process. This ModelState will be empty before model binding happens. /// Gets model state after the model binding process. This ModelState will be empty before model binding
/// happens.
/// </summary> /// </summary>
public ModelStateDictionary ModelState public ModelStateDictionary ModelState
{ {

View File

@ -15,14 +15,15 @@ namespace System.Collections.Generic
internal static class CollectionExtensions internal static class CollectionExtensions
{ {
/// <summary> /// <summary>
/// Return a new array with the value added to the end. Slow and best suited to long lived arrays with few writes relative to reads. /// Return a new array with the value added to the end. Slow and best suited to long lived arrays with few
/// writes relative to reads.
/// </summary> /// </summary>
public static T[] AppendAndReallocate<T>(this T[] array, T value) public static T[] AppendAndReallocate<T>(this T[] array, T value)
{ {
Debug.Assert(array != null); Debug.Assert(array != null);
int originalLength = array.Length; var originalLength = array.Length;
T[] newArray = new T[originalLength + 1]; var newArray = new T[originalLength + 1];
array.CopyTo(newArray, 0); array.CopyTo(newArray, 0);
newArray[originalLength] = value; newArray[originalLength] = value;
return newArray; return newArray;
@ -36,7 +37,7 @@ namespace System.Collections.Generic
{ {
Debug.Assert(values != null); Debug.Assert(values != null);
T[] array = values as T[]; var array = values as T[];
if (array == null) if (array == null)
{ {
array = values.ToArray(); array = values.ToArray();
@ -52,13 +53,13 @@ namespace System.Collections.Generic
{ {
Debug.Assert(enumerable != null); Debug.Assert(enumerable != null);
Collection<T> collection = enumerable as Collection<T>; var collection = enumerable as Collection<T>;
if (collection != null) if (collection != null)
{ {
return collection; return collection;
} }
// Check for IList so that collection can wrap it instead of copying // Check for IList so that collection can wrap it instead of copying
IList<T> list = enumerable as IList<T>; var list = enumerable as IList<T>;
if (list == null) if (list == null)
{ {
list = new List<T>(enumerable); list = new List<T>(enumerable);
@ -73,7 +74,7 @@ namespace System.Collections.Generic
{ {
Debug.Assert(enumerable != null); Debug.Assert(enumerable != null);
IList<T> list = enumerable as IList<T>; var list = enumerable as IList<T>;
if (list != null) if (list != null)
{ {
return list; return list;
@ -82,8 +83,8 @@ namespace System.Collections.Generic
} }
/// <summary> /// <summary>
/// Return the enumerable as a List of T, copying if required. Optimized for common case where it is an List of T /// Return the enumerable as a List of T, copying if required. Optimized for common case where it is an List of
/// or a ListWrapperCollection of T. Avoid mutating the return value. /// T or a ListWrapperCollection of T. Avoid mutating the return value.
/// </summary> /// </summary>
public static List<T> AsList<T>(this IEnumerable<T> enumerable) public static List<T> AsList<T>(this IEnumerable<T> enumerable)
{ {
@ -127,7 +128,7 @@ namespace System.Collections.Generic
return default(T); return default(T);
case 1: case 1:
T value = list[0]; var value = list[0];
return value; return value;
default: default:
@ -137,18 +138,21 @@ namespace System.Collections.Generic
} }
/// <summary> /// <summary>
/// Returns a single value in list matching type TMatch if there is only one, null if there are none of type TMatch or calls the /// Returns a single value in list matching type TMatch if there is only one, null if there are none of type
/// errorAction with errorArg1 if there is more than one. /// TMatch or calls the errorAction with errorArg1 if there is more than one.
/// </summary> /// </summary>
public static TMatch SingleOfTypeDefaultOrError<TInput, TMatch, TArg1>(this IList<TInput> list, Action<TArg1> errorAction, TArg1 errorArg1) where TMatch : class public static TMatch SingleOfTypeDefaultOrError<TInput, TMatch, TArg1>(
this IList<TInput> list,
Action<TArg1> errorAction,
TArg1 errorArg1) where TMatch : class
{ {
Debug.Assert(list != null); Debug.Assert(list != null);
Debug.Assert(errorAction != null); Debug.Assert(errorAction != null);
TMatch result = null; TMatch result = null;
for (int i = 0; i < list.Count; i++) for (var i = 0; i < list.Count; i++)
{ {
TMatch typedValue = list[i] as TMatch; var typedValue = list[i] as TMatch;
if (typedValue != null) if (typedValue != null)
{ {
if (result == null) if (result == null)
@ -166,15 +170,16 @@ namespace System.Collections.Generic
} }
/// <summary> /// <summary>
/// Convert an ICollection to an array, removing null values. Fast path for case where there are no null values. /// Convert an ICollection to an array, removing null values. Fast path for case where there are no null
/// values.
/// </summary> /// </summary>
public static T[] ToArrayWithoutNulls<T>(this ICollection<T> collection) where T : class public static T[] ToArrayWithoutNulls<T>(this ICollection<T> collection) where T : class
{ {
Debug.Assert(collection != null); Debug.Assert(collection != null);
T[] result = new T[collection.Count]; var result = new T[collection.Count];
int count = 0; var count = 0;
foreach (T value in collection) foreach (var value in collection)
{ {
if (value != null) if (value != null)
{ {
@ -188,38 +193,46 @@ namespace System.Collections.Generic
} }
else else
{ {
T[] trimmedResult = new T[count]; var trimmedResult = new T[count];
Array.Copy(result, trimmedResult, count); Array.Copy(result, trimmedResult, count);
return trimmedResult; return trimmedResult;
} }
} }
/// <summary> /// <summary>
/// Convert the array to a Dictionary using the keySelector to extract keys from values and the specified comparer. Optimized for array input. /// Convert the array to a Dictionary using the keySelector to extract keys from values and the specified
/// comparer. Optimized for array input.
/// </summary> /// </summary>
public static Dictionary<TKey, TValue> ToDictionaryFast<TKey, TValue>(this TValue[] array, Func<TValue, TKey> keySelector, IEqualityComparer<TKey> comparer) public static Dictionary<TKey, TValue> ToDictionaryFast<TKey, TValue>(
this TValue[] array,
Func<TValue, TKey> keySelector,
IEqualityComparer<TKey> comparer)
{ {
Debug.Assert(array != null); Debug.Assert(array != null);
Debug.Assert(keySelector != null); Debug.Assert(keySelector != null);
Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(array.Length, comparer); var dictionary = new Dictionary<TKey, TValue>(array.Length, comparer);
for (int i = 0; i < array.Length; i++) for (var i = 0; i < array.Length; i++)
{ {
TValue value = array[i]; var value = array[i];
dictionary.Add(keySelector(value), value); dictionary.Add(keySelector(value), value);
} }
return dictionary; return dictionary;
} }
/// <summary> /// <summary>
/// Convert the list to a Dictionary using the keySelector to extract keys from values and the specified comparer. Optimized for IList of T input with fast path for array. /// Convert the list to a Dictionary using the keySelector to extract keys from values and the specified
/// comparer. Optimized for IList of T input with fast path for array.
/// </summary> /// </summary>
public static Dictionary<TKey, TValue> ToDictionaryFast<TKey, TValue>(this IList<TValue> list, Func<TValue, TKey> keySelector, IEqualityComparer<TKey> comparer) public static Dictionary<TKey, TValue> ToDictionaryFast<TKey, TValue>(
this IList<TValue> list,
Func<TValue, TKey> keySelector,
IEqualityComparer<TKey> comparer)
{ {
Debug.Assert(list != null); Debug.Assert(list != null);
Debug.Assert(keySelector != null); Debug.Assert(keySelector != null);
TValue[] array = list as TValue[]; var array = list as TValue[];
if (array != null) if (array != null)
{ {
return ToDictionaryFast(array, keySelector, comparer); return ToDictionaryFast(array, keySelector, comparer);
@ -228,25 +241,29 @@ namespace System.Collections.Generic
} }
/// <summary> /// <summary>
/// Convert the enumerable to a Dictionary using the keySelector to extract keys from values and the specified comparer. Fast paths for array and IList of T. /// Convert the enumerable to a Dictionary using the keySelector to extract keys from values and the specified
/// comparer. Fast paths for array and IList of T.
/// </summary> /// </summary>
public static Dictionary<TKey, TValue> ToDictionaryFast<TKey, TValue>(this IEnumerable<TValue> enumerable, Func<TValue, TKey> keySelector, IEqualityComparer<TKey> comparer) public static Dictionary<TKey, TValue> ToDictionaryFast<TKey, TValue>(
this IEnumerable<TValue> enumerable,
Func<TValue, TKey> keySelector,
IEqualityComparer<TKey> comparer)
{ {
Debug.Assert(enumerable != null); Debug.Assert(enumerable != null);
Debug.Assert(keySelector != null); Debug.Assert(keySelector != null);
TValue[] array = enumerable as TValue[]; var array = enumerable as TValue[];
if (array != null) if (array != null)
{ {
return ToDictionaryFast(array, keySelector, comparer); return ToDictionaryFast(array, keySelector, comparer);
} }
IList<TValue> list = enumerable as IList<TValue>; var list = enumerable as IList<TValue>;
if (list != null) if (list != null)
{ {
return ToDictionaryFastNoCheck(list, keySelector, comparer); return ToDictionaryFastNoCheck(list, keySelector, comparer);
} }
Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(comparer); var dictionary = new Dictionary<TKey, TValue>(comparer);
foreach (TValue value in enumerable) foreach (var value in enumerable)
{ {
dictionary.Add(keySelector(value), value); dictionary.Add(keySelector(value), value);
} }
@ -254,18 +271,22 @@ namespace System.Collections.Generic
} }
/// <summary> /// <summary>
/// Convert the list to a Dictionary using the keySelector to extract keys from values and the specified comparer. Optimized for IList of T input. No checking for other types. /// Convert the list to a Dictionary using the keySelector to extract keys from values and the specified
/// comparer. Optimized for IList of T input. No checking for other types.
/// </summary> /// </summary>
private static Dictionary<TKey, TValue> ToDictionaryFastNoCheck<TKey, TValue>(IList<TValue> list, Func<TValue, TKey> keySelector, IEqualityComparer<TKey> comparer) private static Dictionary<TKey, TValue> ToDictionaryFastNoCheck<TKey, TValue>(
IList<TValue> list,
Func<TValue, TKey> keySelector,
IEqualityComparer<TKey> comparer)
{ {
Debug.Assert(list != null); Debug.Assert(list != null);
Debug.Assert(keySelector != null); Debug.Assert(keySelector != null);
int listCount = list.Count; var listCount = list.Count;
Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(listCount, comparer); var dictionary = new Dictionary<TKey, TValue>(listCount, comparer);
for (int i = 0; i < listCount; i++) for (var i = 0; i < listCount; i++)
{ {
TValue value = list[i]; var value = list[i];
dictionary.Add(keySelector(value), value); dictionary.Add(keySelector(value), value);
} }
return dictionary; return dictionary;

View File

@ -9,9 +9,7 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text; using System.Text;
using System.Web.Http;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using System.Net.Http.Formatting;
namespace System.Net.Http.Formatting namespace System.Net.Http.Formatting
{ {
@ -48,35 +46,39 @@ namespace System.Net.Http.Formatting
public bool ExcludeMatchOnTypeOnly { get; private set; } public bool ExcludeMatchOnTypeOnly { get; private set; }
/// <summary> /// <summary>
/// Performs content negotiating by selecting the most appropriate <see cref="MediaTypeFormatter"/> out of the passed in /// Performs content negotiating by selecting the most appropriate <see cref="MediaTypeFormatter"/> out of the
/// <paramref name="formatters"/> for the given <paramref name="request"/> that can serialize an object of the given /// passed in <paramref name="formatters"/> for the given <paramref name="request"/> that can serialize an
/// <paramref name="type"/>. /// object of the given <paramref name="type"/>.
/// </summary> /// </summary>
/// <param name="type">The type to be serialized.</param> /// <param name="type">The type to be serialized.</param>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param> /// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param>
/// <returns>The result of the negotiation containing the most appropriate <see cref="MediaTypeFormatter"/> instance, /// <returns>The result of the negotiation containing the most appropriate <see cref="MediaTypeFormatter"/>
/// or <c>null</c> if there is no appropriate formatter.</returns> /// instance, or <c>null</c> if there is no appropriate formatter.</returns>
public virtual ContentNegotiationResult Negotiate([NotNull] Type type, [NotNull] HttpRequestMessage request, [NotNull] IEnumerable<MediaTypeFormatter> formatters) public virtual ContentNegotiationResult Negotiate(
[NotNull] Type type,
[NotNull] HttpRequestMessage request,
[NotNull] IEnumerable<MediaTypeFormatter> formatters)
{ {
// Go through each formatter to compute how well it matches. // Go through each formatter to compute how well it matches.
Collection<MediaTypeFormatterMatch> matches = ComputeFormatterMatches(type, request, formatters); var matches = ComputeFormatterMatches(type, request, formatters);
// Select best formatter match among the matches // Select best formatter match among the matches
MediaTypeFormatterMatch bestFormatterMatch = SelectResponseMediaTypeFormatter(matches); var bestFormatterMatch = SelectResponseMediaTypeFormatter(matches);
// We found a best formatter // We found a best formatter
if (bestFormatterMatch != null) if (bestFormatterMatch != null)
{ {
// Find the best character encoding for the selected formatter // Find the best character encoding for the selected formatter
Encoding bestEncodingMatch = SelectResponseCharacterEncoding(request, bestFormatterMatch.Formatter); var bestEncodingMatch = SelectResponseCharacterEncoding(request, bestFormatterMatch.Formatter);
if (bestEncodingMatch != null) if (bestEncodingMatch != null)
{ {
bestFormatterMatch.MediaType.CharSet = bestEncodingMatch.WebName; bestFormatterMatch.MediaType.CharSet = bestEncodingMatch.WebName;
} }
MediaTypeHeaderValue bestMediaType = bestFormatterMatch.MediaType; var bestMediaType = bestFormatterMatch.MediaType;
MediaTypeFormatter bestFormatter = bestFormatterMatch.Formatter.GetPerRequestFormatterInstance(type, request, bestMediaType); var bestFormatter =
bestFormatterMatch.Formatter.GetPerRequestFormatterInstance(type, request, bestMediaType);
return new ContentNegotiationResult(bestFormatter, bestMediaType); return new ContentNegotiationResult(bestFormatter, bestMediaType);
} }
@ -84,25 +86,28 @@ namespace System.Net.Http.Formatting
} }
/// <summary> /// <summary>
/// Determine how well each formatter matches by associating a <see cref="MediaTypeFormatterMatchRanking"/> value /// Determine how well each formatter matches by associating a <see cref="MediaTypeFormatterMatchRanking"/>
/// with the formatter. Then associate the quality of the match based on q-factors and other parameters. The result of this /// value with the formatter. Then associate the quality of the match based on q-factors and other parameters.
/// method is a collection of the matches found categorized and assigned a quality value. /// The result of this method is a collection of the matches found categorized and assigned a quality value.
/// </summary> /// </summary>
/// <param name="type">The type to be serialized.</param> /// <param name="type">The type to be serialized.</param>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param> /// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param>
/// <returns>A collection containing all the matches.</returns> /// <returns>A collection containing all the matches.</returns>
protected virtual Collection<MediaTypeFormatterMatch> ComputeFormatterMatches([NotNull] Type type, [NotNull] HttpRequestMessage request, [NotNull] IEnumerable<MediaTypeFormatter> formatters) protected virtual Collection<MediaTypeFormatterMatch> ComputeFormatterMatches(
[NotNull] Type type,
[NotNull] HttpRequestMessage request,
[NotNull] IEnumerable<MediaTypeFormatter> formatters)
{ {
IEnumerable<MediaTypeWithQualityHeaderValue> sortedAcceptValues = null; IEnumerable<MediaTypeWithQualityHeaderValue> sortedAcceptValues = null;
// Go through each formatter to find how well it matches. // Go through each formatter to find how well it matches.
ListWrapperCollection<MediaTypeFormatterMatch> matches = new ListWrapperCollection<MediaTypeFormatterMatch>(); var matches =
MediaTypeFormatter[] writingFormatters = GetWritingFormatters(formatters); new ListWrapperCollection<MediaTypeFormatterMatch>();
for (int i = 0; i < writingFormatters.Length; i++) var writingFormatters = GetWritingFormatters(formatters);
for (var i = 0; i < writingFormatters.Length; i++)
{ {
MediaTypeFormatter formatter = writingFormatters[i]; var formatter = writingFormatters[i];
MediaTypeFormatterMatch match = null;
// Check first that formatter can write the actual type // Check first that formatter can write the actual type
if (!formatter.CanWriteType(type)) if (!formatter.CanWriteType(type))
@ -117,7 +122,9 @@ namespace System.Net.Http.Formatting
// Sort the Accept header values in descending order based on q-factor // Sort the Accept header values in descending order based on q-factor
sortedAcceptValues = SortMediaTypeWithQualityHeaderValuesByQFactor(request.Headers.Accept); sortedAcceptValues = SortMediaTypeWithQualityHeaderValuesByQFactor(request.Headers.Accept);
} }
if ((match = MatchAcceptHeader(sortedAcceptValues, formatter)) != null)
var match = MatchAcceptHeader(sortedAcceptValues, formatter);
if (match != null)
{ {
matches.Add(match); matches.Add(match);
continue; continue;
@ -132,7 +139,7 @@ namespace System.Net.Http.Formatting
// Check whether we should match on type or stop the matching process. // Check whether we should match on type or stop the matching process.
// The latter is used to generate 406 (Not Acceptable) status codes. // The latter is used to generate 406 (Not Acceptable) status codes.
bool shouldMatchOnType = ShouldMatchOnType(sortedAcceptValues); var shouldMatchOnType = ShouldMatchOnType(sortedAcceptValues);
// Match against the type of object we are writing out // Match against the type of object we are writing out
if (shouldMatchOnType && (match = MatchType(type, formatter)) != null) if (shouldMatchOnType && (match = MatchType(type, formatter)) != null)
@ -150,11 +157,12 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
/// <param name="matches">The collection of matches.</param> /// <param name="matches">The collection of matches.</param>
/// <returns>The <see cref="MediaTypeFormatterMatch"/> determined to be the best match.</returns> /// <returns>The <see cref="MediaTypeFormatterMatch"/> determined to be the best match.</returns>
protected virtual MediaTypeFormatterMatch SelectResponseMediaTypeFormatter([NotNull] ICollection<MediaTypeFormatterMatch> matches) protected virtual MediaTypeFormatterMatch SelectResponseMediaTypeFormatter(
[NotNull] ICollection<MediaTypeFormatterMatch> matches)
{ {
// Performance-sensitive // Performance-sensitive
List<MediaTypeFormatterMatch> matchList = matches.AsList(); var matchList = matches.AsList();
MediaTypeFormatterMatch bestMatchOnType = null; MediaTypeFormatterMatch bestMatchOnType = null;
MediaTypeFormatterMatch bestMatchOnAcceptHeaderLiteral = null; MediaTypeFormatterMatch bestMatchOnAcceptHeaderLiteral = null;
@ -164,9 +172,9 @@ namespace System.Net.Http.Formatting
MediaTypeFormatterMatch bestMatchOnRequestMediaType = null; MediaTypeFormatterMatch bestMatchOnRequestMediaType = null;
// Go through each formatter to find the best match in each category. // Go through each formatter to find the best match in each category.
for (int i = 0; i < matchList.Count; i++) for (var i = 0; i < matchList.Count; i++)
{ {
MediaTypeFormatterMatch match = matchList[i]; var match = matchList[i];
switch (match.Ranking) switch (match.Ranking)
{ {
case MediaTypeFormatterMatchRanking.MatchOnCanWriteType: case MediaTypeFormatterMatchRanking.MatchOnCanWriteType:
@ -186,13 +194,15 @@ namespace System.Net.Http.Formatting
case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange: case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange:
// Matches on accept headers must choose the highest quality match. // Matches on accept headers must choose the highest quality match.
// A match of 0.0 means we won't use it at all. // A match of 0.0 means we won't use it at all.
bestMatchOnAcceptHeaderSubtypeMediaRange = UpdateBestMatch(bestMatchOnAcceptHeaderSubtypeMediaRange, match); bestMatchOnAcceptHeaderSubtypeMediaRange =
UpdateBestMatch(bestMatchOnAcceptHeaderSubtypeMediaRange, match);
break; break;
case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange: case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange:
// Matches on accept headers must choose the highest quality match. // Matches on accept headers must choose the highest quality match.
// A match of 0.0 means we won't use it at all. // A match of 0.0 means we won't use it at all.
bestMatchOnAcceptHeaderAllMediaRange = UpdateBestMatch(bestMatchOnAcceptHeaderAllMediaRange, match); bestMatchOnAcceptHeaderAllMediaRange =
UpdateBestMatch(bestMatchOnAcceptHeaderAllMediaRange, match);
break; break;
case MediaTypeFormatterMatchRanking.MatchOnRequestMediaType: case MediaTypeFormatterMatchRanking.MatchOnRequestMediaType:
@ -206,12 +216,13 @@ namespace System.Net.Http.Formatting
} }
// If we received matches based on both supported media types and from media type mappings, // If we received matches based on both supported media types and from media type mappings,
// we want to give precedence to the media type mappings, but only if their quality is >= that of the supported media type. // we want to give precedence to the media type mappings, but only if their quality is >= that of the
// We do this because media type mappings are the user's extensibility point and must take precedence over normal // supported media type. We do this because media type mappings are the user's extensibility point and must
// supported media types in the case of a tie. The 99% case is where both have quality 1.0. // take precedence over normal supported media types in the case of a tie. The 99% case is where both have
// quality 1.0.
if (bestMatchOnMediaTypeMapping != null) if (bestMatchOnMediaTypeMapping != null)
{ {
MediaTypeFormatterMatch mappingOverride = bestMatchOnMediaTypeMapping; var mappingOverride = bestMatchOnMediaTypeMapping;
mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderLiteral); mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderLiteral);
mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderSubtypeMediaRange); mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderSubtypeMediaRange);
mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderAllMediaRange); mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderAllMediaRange);
@ -256,21 +267,24 @@ namespace System.Net.Http.Formatting
/// If no encoding is found then we use the default for the formatter. /// If no encoding is found then we use the default for the formatter.
/// </summary> /// </summary>
/// <returns>The <see cref="Encoding"/> determined to be the best match.</returns> /// <returns>The <see cref="Encoding"/> determined to be the best match.</returns>
protected virtual Encoding SelectResponseCharacterEncoding([NotNull] HttpRequestMessage request, [NotNull] MediaTypeFormatter formatter) protected virtual Encoding SelectResponseCharacterEncoding(
[NotNull] HttpRequestMessage request,
[NotNull] MediaTypeFormatter formatter)
{ {
// If there are any SupportedEncodings then we pick an encoding // If there are any SupportedEncodings then we pick an encoding
List<Encoding> supportedEncodings = formatter.SupportedEncodings.ToList(); var supportedEncodings = formatter.SupportedEncodings.ToList();
if (supportedEncodings.Count > 0) if (supportedEncodings.Count > 0)
{ {
// Sort Accept-Charset header values // Sort Accept-Charset header values
IEnumerable<StringWithQualityHeaderValue> sortedAcceptCharsetValues = SortStringWithQualityHeaderValuesByQFactor(request.Headers.AcceptCharset); var sortedAcceptCharsetValues =
SortStringWithQualityHeaderValuesByQFactor(request.Headers.AcceptCharset);
// Check for match based on accept-charset headers // Check for match based on accept-charset headers
foreach (StringWithQualityHeaderValue acceptCharset in sortedAcceptCharsetValues) foreach (StringWithQualityHeaderValue acceptCharset in sortedAcceptCharsetValues)
{ {
for (int i = 0; i < supportedEncodings.Count; i++) for (var i = 0; i < supportedEncodings.Count; i++)
{ {
Encoding encoding = supportedEncodings[i]; var encoding = supportedEncodings[i];
if (encoding != null && acceptCharset.Quality != FormattingUtilities.NoMatch && if (encoding != null && acceptCharset.Quality != FormattingUtilities.NoMatch &&
(acceptCharset.Value.Equals(encoding.WebName, StringComparison.OrdinalIgnoreCase) || (acceptCharset.Value.Equals(encoding.WebName, StringComparison.OrdinalIgnoreCase) ||
acceptCharset.Value.Equals("*", StringComparison.Ordinal))) acceptCharset.Value.Equals("*", StringComparison.Ordinal)))
@ -292,17 +306,22 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
/// <param name="sortedAcceptValues">The sorted accept header values to match.</param> /// <param name="sortedAcceptValues">The sorted accept header values to match.</param>
/// <param name="formatter">The formatter to match against.</param> /// <param name="formatter">The formatter to match against.</param>
/// <returns>A <see cref="MediaTypeFormatterMatch"/> indicating the quality of the match or null is no match.</returns> /// <returns>
protected virtual MediaTypeFormatterMatch MatchAcceptHeader([NotNull] IEnumerable<MediaTypeWithQualityHeaderValue> sortedAcceptValues, [NotNull] MediaTypeFormatter formatter) /// A <see cref="MediaTypeFormatterMatch"/> indicating the quality of the match or null is no match.
/// </returns>
protected virtual MediaTypeFormatterMatch MatchAcceptHeader(
[NotNull] IEnumerable<MediaTypeWithQualityHeaderValue> sortedAcceptValues,
[NotNull] MediaTypeFormatter formatter)
{ {
foreach (MediaTypeWithQualityHeaderValue acceptMediaTypeValue in sortedAcceptValues) foreach (MediaTypeWithQualityHeaderValue acceptMediaTypeValue in sortedAcceptValues)
{ {
List<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes.ToList(); var supportedMediaTypes = formatter.SupportedMediaTypes.ToList();
for (int i = 0; i < supportedMediaTypes.Count; i++) for (var i = 0; i < supportedMediaTypes.Count; i++)
{ {
MediaTypeHeaderValue supportedMediaType = supportedMediaTypes[i]; var supportedMediaType = supportedMediaTypes[i];
MediaTypeHeaderValueRange range; MediaTypeHeaderValueRange range;
if (supportedMediaType != null && acceptMediaTypeValue.Quality != FormattingUtilities.NoMatch && if (supportedMediaType != null &&
acceptMediaTypeValue.Quality != FormattingUtilities.NoMatch &&
supportedMediaType.IsSubsetOf(acceptMediaTypeValue, out range)) supportedMediaType.IsSubsetOf(acceptMediaTypeValue, out range))
{ {
MediaTypeFormatterMatchRanking ranking; MediaTypeFormatterMatchRanking ranking;
@ -321,7 +340,11 @@ namespace System.Net.Http.Formatting
break; break;
} }
return new MediaTypeFormatterMatch(formatter, supportedMediaType, acceptMediaTypeValue.Quality, ranking); return new MediaTypeFormatterMatch(
formatter,
supportedMediaType,
acceptMediaTypeValue.Quality,
ranking);
} }
} }
} }
@ -335,21 +358,29 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
/// <param name="request">The request to match.</param> /// <param name="request">The request to match.</param>
/// <param name="formatter">The formatter to match against.</param> /// <param name="formatter">The formatter to match against.</param>
/// <returns>A <see cref="MediaTypeFormatterMatch"/> indicating the quality of the match or null is no match.</returns> /// <returns>
protected virtual MediaTypeFormatterMatch MatchRequestMediaType([NotNull] HttpRequestMessage request, [NotNull] MediaTypeFormatter formatter) /// A <see cref="MediaTypeFormatterMatch"/> indicating the quality of the match or null is no match.
/// </returns>
protected virtual MediaTypeFormatterMatch MatchRequestMediaType(
[NotNull] HttpRequestMessage request,
[NotNull] MediaTypeFormatter formatter)
{ {
if (request.Content != null) if (request.Content != null)
{ {
MediaTypeHeaderValue requestMediaType = request.Content.Headers.ContentType; var requestMediaType = request.Content.Headers.ContentType;
if (requestMediaType != null) if (requestMediaType != null)
{ {
List<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes.ToList(); var supportedMediaTypes = formatter.SupportedMediaTypes.ToList();
for (int i = 0; i < supportedMediaTypes.Count; i++) for (var i = 0; i < supportedMediaTypes.Count; i++)
{ {
MediaTypeHeaderValue supportedMediaType = supportedMediaTypes[i]; var supportedMediaType = supportedMediaTypes[i];
if (supportedMediaType != null && supportedMediaType.IsSubsetOf(requestMediaType)) if (supportedMediaType != null && supportedMediaType.IsSubsetOf(requestMediaType))
{ {
return new MediaTypeFormatterMatch(formatter, supportedMediaType, FormattingUtilities.Match, MediaTypeFormatterMatchRanking.MatchOnRequestMediaType); return new MediaTypeFormatterMatch(
formatter,
supportedMediaType,
FormattingUtilities.Match,
MediaTypeFormatterMatchRanking.MatchOnRequestMediaType);
} }
} }
} }
@ -365,8 +396,11 @@ namespace System.Net.Http.Formatting
/// then we don't match on type unless there are no accept headers. /// then we don't match on type unless there are no accept headers.
/// </summary> /// </summary>
/// <param name="sortedAcceptValues">The sorted accept header values to match.</param> /// <param name="sortedAcceptValues">The sorted accept header values to match.</param>
/// <returns>True if not ExcludeMatchOnTypeOnly and accept headers with a q-factor bigger than 0.0 are present.</returns> /// <returns>
protected virtual bool ShouldMatchOnType([NotNull] IEnumerable<MediaTypeWithQualityHeaderValue> sortedAcceptValues) /// True if not ExcludeMatchOnTypeOnly and accept headers with a q-factor bigger than 0.0 are present.
/// </returns>
protected virtual bool ShouldMatchOnType(
[NotNull] IEnumerable<MediaTypeWithQualityHeaderValue> sortedAcceptValues)
{ {
return !(ExcludeMatchOnTypeOnly && sortedAcceptValues.Any()); return !(ExcludeMatchOnTypeOnly && sortedAcceptValues.Any());
} }
@ -376,18 +410,26 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
/// <param name="type">The type to be serialized.</param> /// <param name="type">The type to be serialized.</param>
/// <param name="formatter">The formatter we are matching against.</param> /// <param name="formatter">The formatter we are matching against.</param>
/// <returns>A <see cref="MediaTypeFormatterMatch"/> indicating the quality of the match or null is no match.</returns> /// <returns>
protected virtual MediaTypeFormatterMatch MatchType([NotNull] Type type, [NotNull] MediaTypeFormatter formatter) /// A <see cref="MediaTypeFormatterMatch"/> indicating the quality of the match or null is no match.
/// </returns>
protected virtual MediaTypeFormatterMatch MatchType(
[NotNull] Type type,
[NotNull] MediaTypeFormatter formatter)
{ {
// We already know that we do match on type -- otherwise we wouldn't even be called -- // We already know that we do match on type -- otherwise we wouldn't even be called --
// so this is just a matter of determining how we match. // so this is just a matter of determining how we match.
MediaTypeHeaderValue mediaType = null; MediaTypeHeaderValue mediaType = null;
List<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes.ToList(); var supportedMediaTypes = formatter.SupportedMediaTypes.ToList();
if (supportedMediaTypes.Count > 0) if (supportedMediaTypes.Count > 0)
{ {
mediaType = supportedMediaTypes[0]; mediaType = supportedMediaTypes[0];
} }
return new MediaTypeFormatterMatch(formatter, mediaType, FormattingUtilities.Match, MediaTypeFormatterMatchRanking.MatchOnCanWriteType); return new MediaTypeFormatterMatch(
formatter,
mediaType,
FormattingUtilities.Match,
MediaTypeFormatterMatchRanking.MatchOnCanWriteType);
} }
/// <summary> /// <summary>
@ -396,13 +438,16 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
/// <param name="headerValues">The header values to sort.</param> /// <param name="headerValues">The header values to sort.</param>
/// <returns>The sorted header values.</returns> /// <returns>The sorted header values.</returns>
protected virtual IEnumerable<MediaTypeWithQualityHeaderValue> SortMediaTypeWithQualityHeaderValuesByQFactor(ICollection<MediaTypeWithQualityHeaderValue> headerValues) protected virtual IEnumerable<MediaTypeWithQualityHeaderValue> SortMediaTypeWithQualityHeaderValuesByQFactor(
ICollection<MediaTypeWithQualityHeaderValue> headerValues)
{ {
if (headerValues.Count > 1) if (headerValues.Count > 1)
{ {
// Use OrderBy() instead of Array.Sort() as it performs fewer comparisons. In this case the comparisons // Use OrderBy() instead of Array.Sort() as it performs fewer comparisons. In this case the comparisons
// are quite expensive so OrderBy() performs better. // are quite expensive so OrderBy() performs better.
return headerValues.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer).ToArray(); return headerValues
.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer)
.ToArray();
} }
else else
{ {
@ -411,18 +456,21 @@ namespace System.Net.Http.Formatting
} }
/// <summary> /// <summary>
/// Sort Accept-Charset, Accept-Encoding, Accept-Language and related header field values with similar syntax rules /// Sort Accept-Charset, Accept-Encoding, Accept-Language and related header field values with similar syntax
/// (if more than 1) in descending order based on q-factor. /// rules (if more than 1) in descending order based on q-factor.
/// </summary> /// </summary>
/// <param name="headerValues">The header values to sort.</param> /// <param name="headerValues">The header values to sort.</param>
/// <returns>The sorted header values.</returns> /// <returns>The sorted header values.</returns>
protected virtual IEnumerable<StringWithQualityHeaderValue> SortStringWithQualityHeaderValuesByQFactor([NotNull] ICollection<StringWithQualityHeaderValue> headerValues) protected virtual IEnumerable<StringWithQualityHeaderValue> SortStringWithQualityHeaderValuesByQFactor(
[NotNull] ICollection<StringWithQualityHeaderValue> headerValues)
{ {
if (headerValues.Count > 1) if (headerValues.Count > 1)
{ {
// Use OrderBy() instead of Array.Sort() as it performs fewer comparisons. In this case the comparisons // Use OrderBy() instead of Array.Sort() as it performs fewer comparisons. In this case the comparisons
// are quite expensive so OrderBy() performs better. // are quite expensive so OrderBy() performs better.
return headerValues.OrderByDescending(m => m, StringWithQualityHeaderValueComparer.QualityComparer).ToArray(); return headerValues
.OrderByDescending(m => m, StringWithQualityHeaderValueComparer.QualityComparer)
.ToArray();
} }
else else
{ {
@ -431,10 +479,12 @@ namespace System.Net.Http.Formatting
} }
/// <summary> /// <summary>
/// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise returns the /// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise
/// current match. /// returns the current match.
/// </summary> /// </summary>
protected virtual MediaTypeFormatterMatch UpdateBestMatch(MediaTypeFormatterMatch current, MediaTypeFormatterMatch potentialReplacement) protected virtual MediaTypeFormatterMatch UpdateBestMatch(
MediaTypeFormatterMatch current,
MediaTypeFormatterMatch potentialReplacement)
{ {
if (potentialReplacement == null) if (potentialReplacement == null)
{ {
@ -452,7 +502,6 @@ namespace System.Net.Http.Formatting
private static MediaTypeFormatter[] GetWritingFormatters(IEnumerable<MediaTypeFormatter> formatters) private static MediaTypeFormatter[] GetWritingFormatters(IEnumerable<MediaTypeFormatter> formatters)
{ {
Debug.Assert(formatters != null); Debug.Assert(formatters != null);
MediaTypeFormatterCollection formatterCollection = formatters as MediaTypeFormatterCollection;
return formatters.AsArray(); return formatters.AsArray();
} }
} }

View File

@ -8,10 +8,9 @@ using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http.Formatting; using System.Net.Http.Formatting;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Runtime.Serialization; using System.Reflection;
using System.Xml; using System.Xml;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Reflection;
namespace System.Net.Http namespace System.Net.Http
{ {
@ -161,7 +160,9 @@ namespace System.Net.Http
/// <returns></returns> /// <returns></returns>
public static XmlDictionaryReaderQuotas CreateDefaultReaderQuotas() public static XmlDictionaryReaderQuotas CreateDefaultReaderQuotas()
{ {
#if NETFX_CORE // MaxDepth is a DOS mitigation. We don't support MaxDepth in portable libraries because it is strictly client side. // MaxDepth is a DOS mitigation. We don't support MaxDepth in portable libraries because it is strictly
// client side.
#if NETFX_CORE
return XmlDictionaryReaderQuotas.Max; return XmlDictionaryReaderQuotas.Max;
#else #else
return new XmlDictionaryReaderQuotas() return new XmlDictionaryReaderQuotas()
@ -187,7 +188,9 @@ namespace System.Net.Http
return token; return token;
} }
if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1) if (token.StartsWith("\"", StringComparison.Ordinal) &&
token.EndsWith("\"", StringComparison.Ordinal) &&
token.Length > 1)
{ {
return token.Substring(1, token.Length - 2); return token.Substring(1, token.Length - 2);
} }

View File

@ -15,20 +15,27 @@ namespace System.Net.Http.Formatting
public interface IContentNegotiator public interface IContentNegotiator
{ {
/// <summary> /// <summary>
/// Performs content negotiating by selecting the most appropriate <see cref="MediaTypeFormatter"/> out of the passed in /// Performs content negotiating by selecting the most appropriate <see cref="MediaTypeFormatter"/> out of the
/// <paramref name="formatters"/> for the given <paramref name="request"/> that can serialize an object of the given /// passed in <paramref name="formatters"/> for the given <paramref name="request"/> that can serialize an
/// <paramref name="type"/>. /// object of the given <paramref name="type"/>.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Implementations of this method should call <see cref="MediaTypeFormatter.GetPerRequestFormatterInstance(Type, HttpRequestMessage, MediaTypeHeaderValue)"/> /// Implementations of this method should call <see cref="MediaTypeFormatter.GetPerRequestFormatterInstance"/>
/// on the selected <see cref="MediaTypeFormatter">formatter</see> and return the result of that method. /// on the selected <see cref="MediaTypeFormatter">formatter</see> and return the result of that method.
/// </remarks> /// </remarks>
/// <param name="type">The type to be serialized.</param> /// <param name="type">The type to be serialized.</param>
/// <param name="request">Request message, which contains the header values used to perform negotiation.</param> /// <param name="request">
/// Request message, which contains the header values used to perform negotiation.
/// </param>
/// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param> /// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param>
/// <returns>The result of the negotiation containing the most appropriate <see cref="MediaTypeFormatter"/> instance, /// <returns>
/// or <c>null</c> if there is no appropriate formatter.</returns> /// The result of the negotiation containing the most appropriate <see cref="MediaTypeFormatter"/> instance,
ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters); /// or <c>null</c> if there is no appropriate formatter.
/// </returns>
ContentNegotiationResult Negotiate(
Type type,
HttpRequestMessage request,
IEnumerable<MediaTypeFormatter> formatters);
} }
} }
#endif #endif

View File

@ -12,13 +12,20 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
internal static class MediaTypeConstants internal static class MediaTypeConstants
{ {
private static readonly MediaTypeHeaderValue _defaultApplicationXmlMediaType = new MediaTypeHeaderValue("application/xml"); private static readonly MediaTypeHeaderValue _defaultApplicationXmlMediaType =
private static readonly MediaTypeHeaderValue _defaultTextXmlMediaType = new MediaTypeHeaderValue("text/xml"); new MediaTypeHeaderValue("application/xml");
private static readonly MediaTypeHeaderValue _defaultApplicationJsonMediaType = new MediaTypeHeaderValue("application/json"); private static readonly MediaTypeHeaderValue _defaultTextXmlMediaType =
private static readonly MediaTypeHeaderValue _defaultTextJsonMediaType = new MediaTypeHeaderValue("text/json"); new MediaTypeHeaderValue("text/xml");
private static readonly MediaTypeHeaderValue _defaultApplicationOctetStreamMediaType = new MediaTypeHeaderValue("application/octet-stream"); private static readonly MediaTypeHeaderValue _defaultApplicationJsonMediaType =
private static readonly MediaTypeHeaderValue _defaultApplicationFormUrlEncodedMediaType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); new MediaTypeHeaderValue("application/json");
private static readonly MediaTypeHeaderValue _defaultApplicationBsonMediaType = new MediaTypeHeaderValue("application/bson"); private static readonly MediaTypeHeaderValue _defaultTextJsonMediaType =
new MediaTypeHeaderValue("text/json");
private static readonly MediaTypeHeaderValue _defaultApplicationOctetStreamMediaType =
new MediaTypeHeaderValue("application/octet-stream");
private static readonly MediaTypeHeaderValue _defaultApplicationFormUrlEncodedMediaType =
new MediaTypeHeaderValue("application/x-www-form-urlencoded");
private static readonly MediaTypeHeaderValue _defaultApplicationBsonMediaType =
new MediaTypeHeaderValue("application/bson");
/// <summary> /// <summary>
/// Gets a <see cref="MediaTypeHeaderValue"/> instance representing <c>application/octet-stream</c>. /// Gets a <see cref="MediaTypeHeaderValue"/> instance representing <c>application/octet-stream</c>.

View File

@ -4,7 +4,6 @@
#if ASPNETCORE50 #if ASPNETCORE50
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Web.Http;
namespace System.Net.Http.Formatting namespace System.Net.Http.Formatting
{ {
@ -17,10 +16,19 @@ namespace System.Net.Http.Formatting
/// Initializes a new instance of the <see cref="MediaTypeFormatterMatch"/> class. /// Initializes a new instance of the <see cref="MediaTypeFormatterMatch"/> class.
/// </summary> /// </summary>
/// <param name="formatter">The matching formatter.</param> /// <param name="formatter">The matching formatter.</param>
/// <param name="mediaType">The media type. Can be <c>null</c> in which case the media type <c>application/octet-stream</c> is used.</param> /// <param name="mediaType">
/// <param name="quality">The quality of the match. Can be <c>null</c> in which case it is considered a full match with a value of 1.0</param> /// The media type. Can be <c>null</c> in which case the media type <c>application/octet-stream</c> is used.
/// </param>
/// <param name="quality">
/// The quality of the match. Can be <c>null</c> in which case it is considered a full match with a value of
/// 1.0.
/// </param>
/// <param name="ranking">The kind of match.</param> /// <param name="ranking">The kind of match.</param>
public MediaTypeFormatterMatch(MediaTypeFormatter formatter, MediaTypeHeaderValue mediaType, double? quality, MediaTypeFormatterMatchRanking ranking) public MediaTypeFormatterMatch(
MediaTypeFormatter formatter,
MediaTypeHeaderValue mediaType,
double? quality,
MediaTypeFormatterMatchRanking ranking)
{ {
Formatter = formatter; Formatter = formatter;
MediaType = mediaType != null ? mediaType : MediaTypeConstants.ApplicationOctetStreamMediaType; MediaType = mediaType != null ? mediaType : MediaTypeConstants.ApplicationOctetStreamMediaType;

View File

@ -3,12 +3,10 @@
#if ASPNETCORE50 #if ASPNETCORE50
using Microsoft.AspNet.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using Microsoft.AspNet.Mvc;
namespace System.Net.Http.Formatting namespace System.Net.Http.Formatting
{ {
@ -20,10 +18,11 @@ namespace System.Net.Http.Formatting
/// <summary> /// <summary>
/// Determines whether two <see cref="MediaTypeHeaderValue"/> instances match. The instance /// Determines whether two <see cref="MediaTypeHeaderValue"/> instances match. The instance
/// <paramref name="mediaType1"/> is said to match <paramref name="mediaType2"/> if and only if /// <paramref name="mediaType1"/> is said to match <paramref name="mediaType2"/> if and only if
/// <paramref name="mediaType1"/> is a strict subset of the values and parameters of <paramref name="mediaType2"/>. /// <paramref name="mediaType1"/> is a strict subset of the values and parameters of
/// <paramref name="mediaType2"/>.
/// That is, if the media type and media type parameters of <paramref name="mediaType1"/> are all present /// That is, if the media type and media type parameters of <paramref name="mediaType1"/> are all present
/// and match those of <paramref name="mediaType2"/> then it is a match even though <paramref name="mediaType2"/> may have additional /// and match those of <paramref name="mediaType2"/> then it is a match even though
/// parameters. /// <paramref name="mediaType2"/> may have additional parameters.
/// </summary> /// </summary>
/// <param name="mediaType1">The first media type.</param> /// <param name="mediaType1">The first media type.</param>
/// <param name="mediaType2">The second media type.</param> /// <param name="mediaType2">The second media type.</param>
@ -37,16 +36,23 @@ namespace System.Net.Http.Formatting
/// <summary> /// <summary>
/// Determines whether two <see cref="MediaTypeHeaderValue"/> instances match. The instance /// Determines whether two <see cref="MediaTypeHeaderValue"/> instances match. The instance
/// <paramref name="mediaType1"/> is said to match <paramref name="mediaType2"/> if and only if /// <paramref name="mediaType1"/> is said to match <paramref name="mediaType2"/> if and only if
/// <paramref name="mediaType1"/> is a strict subset of the values and parameters of <paramref name="mediaType2"/>. /// <paramref name="mediaType1"/> is a strict subset of the values and parameters of
/// <paramref name="mediaType2"/>.
/// That is, if the media type and media type parameters of <paramref name="mediaType1"/> are all present /// That is, if the media type and media type parameters of <paramref name="mediaType1"/> are all present
/// and match those of <paramref name="mediaType2"/> then it is a match even though <paramref name="mediaType2"/> may have additional /// and match those of <paramref name="mediaType2"/> then it is a match even though
/// parameters. /// <paramref name="mediaType2"/> may have additional parameters.
/// </summary> /// </summary>
/// <param name="mediaType1">The first media type.</param> /// <param name="mediaType1">The first media type.</param>
/// <param name="mediaType2">The second media type.</param> /// <param name="mediaType2">The second media type.</param>
/// <param name="mediaType2Range">Indicates whether <paramref name="mediaType2"/> is a regular media type, a subtype media range, or a full media range</param> /// <param name="mediaType2Range">
/// Indicates whether <paramref name="mediaType2"/> is a regular media type, a subtype media range, or a full
/// media range.
/// </param>
/// <returns><c>true</c> if this is a subset of <paramref name="mediaType2"/>; false otherwise.</returns> /// <returns><c>true</c> if this is a subset of <paramref name="mediaType2"/>; false otherwise.</returns>
public static bool IsSubsetOf(this MediaTypeHeaderValue mediaType1, MediaTypeHeaderValue mediaType2, out MediaTypeHeaderValueRange mediaType2Range) public static bool IsSubsetOf(
this MediaTypeHeaderValue mediaType1,
MediaTypeHeaderValue mediaType2,
out MediaTypeHeaderValueRange mediaType2Range)
{ {
// Performance-sensitive // Performance-sensitive
Debug.Assert(mediaType1 != null); Debug.Assert(mediaType1 != null);
@ -57,8 +63,8 @@ namespace System.Net.Http.Formatting
return false; return false;
} }
ParsedMediaTypeHeaderValue parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1); var parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
ParsedMediaTypeHeaderValue parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2); var parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
mediaType2Range = parsedMediaType2.IsAllMediaRange ? MediaTypeHeaderValueRange.AllMediaRange : mediaType2Range = parsedMediaType2.IsAllMediaRange ? MediaTypeHeaderValueRange.AllMediaRange :
parsedMediaType2.IsSubtypeMediaRange ? MediaTypeHeaderValueRange.SubtypeMediaRange : parsedMediaType2.IsSubtypeMediaRange ? MediaTypeHeaderValueRange.SubtypeMediaRange :
MediaTypeHeaderValueRange.None; MediaTypeHeaderValueRange.None;
@ -80,18 +86,19 @@ namespace System.Net.Http.Formatting
// So far we either have a full match or a subset match. Now check that all of // So far we either have a full match or a subset match. Now check that all of
// mediaType1's parameters are present and equal in mediatype2 // mediaType1's parameters are present and equal in mediatype2
// Optimize for the common case where the parameters inherit from Collection<T> and cache the count which is faster for Collection<T>. // Optimize for the common case where the parameters inherit from Collection<T> and cache the count which
Collection<NameValueHeaderValue> parameters1 = mediaType1.Parameters.AsCollection(); // is faster for Collection<T>.
int parameterCount1 = parameters1.Count; var parameters1 = mediaType1.Parameters.AsCollection();
Collection<NameValueHeaderValue> parameters2 = mediaType2.Parameters.AsCollection(); var parameterCount1 = parameters1.Count;
int parameterCount2 = parameters2.Count; var parameters2 = mediaType2.Parameters.AsCollection();
for (int i = 0; i < parameterCount1; i++) var parameterCount2 = parameters2.Count;
for (var i = 0; i < parameterCount1; i++)
{ {
NameValueHeaderValue parameter1 = parameters1[i]; var parameter1 = parameters1[i];
bool found = false; var found = false;
for (int j = 0; j < parameterCount2; j++) for (var j = 0; j < parameterCount2; j++)
{ {
NameValueHeaderValue parameter2 = parameters2[j]; var parameter2 = parameters2[j];
if (parameter1.Equals(parameter2)) if (parameter1.Equals(parameter2))
{ {
found = true; found = true;

View File

@ -15,7 +15,8 @@ namespace System.Net.Http.Formatting
/// header field q-values. /// header field q-values.
internal class MediaTypeWithQualityHeaderValueComparer : IComparer<MediaTypeWithQualityHeaderValue> internal class MediaTypeWithQualityHeaderValueComparer : IComparer<MediaTypeWithQualityHeaderValue>
{ {
private static readonly MediaTypeWithQualityHeaderValueComparer _mediaTypeComparer = new MediaTypeWithQualityHeaderValueComparer(); private static readonly MediaTypeWithQualityHeaderValueComparer _mediaTypeComparer =
new MediaTypeWithQualityHeaderValueComparer();
private MediaTypeWithQualityHeaderValueComparer() private MediaTypeWithQualityHeaderValueComparer()
{ {
@ -27,11 +28,12 @@ namespace System.Net.Http.Formatting
} }
/// <summary> /// <summary>
/// Compares two <see cref="MediaTypeWithQualityHeaderValue"/> based on their quality value (a.k.a their "q-value"). /// Compares two <see cref="MediaTypeWithQualityHeaderValue"/> based on their quality value (a.k.a their
/// Values with identical q-values are considered equal (i.e the result is 0) with the exception that sub-type wild-cards are /// "q-value"). Values with identical q-values are considered equal (i.e the result is 0) with the exception
/// considered less than specific media types and full wild-cards are considered less than sub-type wild-cards. This allows to /// that sub-type wild-cards are considered less than specific media types and full wild-cards are considered
/// sort a sequence of <see cref="StringWithQualityHeaderValue"/> following their q-values in the order of specific media types, /// less than sub-type wild-cards. This allows to sort a sequence of <see cref="StringWithQualityHeaderValue"/>
/// sub-type wildcards, and last any full wild-cards. /// following their q-values in the order of specific media types, subtype wild-cards, and last any full
/// wild-cards.
/// </summary> /// </summary>
/// <param name="mediaType1">The first <see cref="MediaTypeWithQualityHeaderValue"/> to compare.</param> /// <param name="mediaType1">The first <see cref="MediaTypeWithQualityHeaderValue"/> to compare.</param>
/// <param name="mediaType2">The second <see cref="MediaTypeWithQualityHeaderValue"/> to compare.</param> /// <param name="mediaType2">The second <see cref="MediaTypeWithQualityHeaderValue"/> to compare.</param>
@ -46,12 +48,11 @@ namespace System.Net.Http.Formatting
return 0; return 0;
} }
int returnValue = CompareBasedOnQualityFactor(mediaType1, mediaType2); var returnValue = CompareBasedOnQualityFactor(mediaType1, mediaType2);
if (returnValue == 0) if (returnValue == 0)
{ {
ParsedMediaTypeHeaderValue parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1); var parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
ParsedMediaTypeHeaderValue parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2); var parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
if (!parsedMediaType1.TypesEqual(ref parsedMediaType2)) if (!parsedMediaType1.TypesEqual(ref parsedMediaType2))
{ {
@ -88,14 +89,16 @@ namespace System.Net.Http.Formatting
return returnValue; return returnValue;
} }
private static int CompareBasedOnQualityFactor(MediaTypeWithQualityHeaderValue mediaType1, MediaTypeWithQualityHeaderValue mediaType2) private static int CompareBasedOnQualityFactor(
MediaTypeWithQualityHeaderValue mediaType1,
MediaTypeWithQualityHeaderValue mediaType2)
{ {
Debug.Assert(mediaType1 != null); Debug.Assert(mediaType1 != null);
Debug.Assert(mediaType2 != null); Debug.Assert(mediaType2 != null);
double mediaType1Quality = mediaType1.Quality ?? FormattingUtilities.Match; var mediaType1Quality = mediaType1.Quality ?? FormattingUtilities.Match;
double mediaType2Quality = mediaType2.Quality ?? FormattingUtilities.Match; var mediaType2Quality = mediaType2.Quality ?? FormattingUtilities.Match;
double qualityDifference = mediaType1Quality - mediaType2Quality; var qualityDifference = mediaType1Quality - mediaType2Quality;
if (qualityDifference < 0) if (qualityDifference < 0)
{ {
return -1; return -1;

View File

@ -8,7 +8,7 @@ using System.Net.Http.Headers;
namespace System.Net.Http.Formatting namespace System.Net.Http.Formatting
{ {
// This type is instanciated by frequently called comparison methods so is very performance sensitive // This type is instantiated by frequently called comparison methods so is very performance sensitive
internal struct ParsedMediaTypeHeaderValue internal struct ParsedMediaTypeHeaderValue
{ {
private const char MediaRangeAsterisk = '*'; private const char MediaRangeAsterisk = '*';
@ -22,13 +22,15 @@ namespace System.Net.Http.Formatting
public ParsedMediaTypeHeaderValue(MediaTypeHeaderValue mediaTypeHeaderValue) public ParsedMediaTypeHeaderValue(MediaTypeHeaderValue mediaTypeHeaderValue)
{ {
Debug.Assert(mediaTypeHeaderValue != null); Debug.Assert(mediaTypeHeaderValue != null);
string mediaType = _mediaType = mediaTypeHeaderValue.MediaType; var mediaType = _mediaType = mediaTypeHeaderValue.MediaType;
_delimiterIndex = mediaType.IndexOf(MediaTypeSubtypeDelimiter); _delimiterIndex = mediaType.IndexOf(MediaTypeSubtypeDelimiter);
Debug.Assert(_delimiterIndex > 0, "The constructor of the MediaTypeHeaderValue would have failed if there wasn't a type and subtype."); Debug.Assert(
_delimiterIndex > 0,
"The constructor of the MediaTypeHeaderValue would have failed if there wasn't a type and subtype.");
_isAllMediaRange = false; _isAllMediaRange = false;
_isSubtypeMediaRange = false; _isSubtypeMediaRange = false;
int mediaTypeLength = mediaType.Length; var mediaTypeLength = mediaType.Length;
if (_delimiterIndex == mediaTypeLength - 2) if (_delimiterIndex == mediaTypeLength - 2)
{ {
if (mediaType[mediaTypeLength - 1] == MediaRangeAsterisk) if (mediaType[mediaTypeLength - 1] == MediaRangeAsterisk)
@ -58,17 +60,31 @@ namespace System.Net.Http.Formatting
{ {
return false; return false;
} }
return String.Compare(_mediaType, 0, other._mediaType, 0, _delimiterIndex, StringComparison.OrdinalIgnoreCase) == 0;
return string.Compare(
strA: _mediaType,
indexA: 0,
strB: other._mediaType,
indexB: 0,
length: _delimiterIndex,
comparisonType: StringComparison.OrdinalIgnoreCase) == 0;
} }
public bool SubTypesEqual(ref ParsedMediaTypeHeaderValue other) public bool SubTypesEqual(ref ParsedMediaTypeHeaderValue other)
{ {
int _subTypeLength = _mediaType.Length - _delimiterIndex - 1; var _subTypeLength = _mediaType.Length - _delimiterIndex - 1;
if (_subTypeLength != other._mediaType.Length - other._delimiterIndex - 1) if (_subTypeLength != other._mediaType.Length - other._delimiterIndex - 1)
{ {
return false; return false;
} }
return String.Compare(_mediaType, _delimiterIndex + 1, other._mediaType, other._delimiterIndex + 1, _subTypeLength, StringComparison.OrdinalIgnoreCase) == 0;
return string.Compare(
strA: _mediaType,
indexA: _delimiterIndex + 1,
strB: other._mediaType,
indexB: other._delimiterIndex + 1,
length: _subTypeLength,
comparisonType: StringComparison.OrdinalIgnoreCase) == 0;
} }
} }
} }

View File

@ -31,10 +31,10 @@ namespace System.Net.Http.Formatting
} }
/// <summary> /// <summary>
/// Compares two <see cref="StringWithQualityHeaderValue"/> based on their quality value (a.k.a their "q-value"). /// Compares two <see cref="StringWithQualityHeaderValue"/> based on their quality value (a.k.a their
/// Values with identical q-values are considered equal (i.e the result is 0) with the exception of wild-card /// "q-value"). Values with identical q-values are considered equal (i.e the result is 0) with the exception of
/// values (i.e. a value of "*") which are considered less than non-wild-card values. This allows to sort /// wild-card values (i.e. a value of "*") which are considered less than non-wild-card values. This allows to
/// a sequence of <see cref="StringWithQualityHeaderValue"/> following their q-values ending up with any /// sort a sequence of <see cref="StringWithQualityHeaderValue"/> following their q-values ending up with any
/// wild-cards at the end. /// wild-cards at the end.
/// </summary> /// </summary>
/// <param name="stringWithQuality1">The first value to compare.</param> /// <param name="stringWithQuality1">The first value to compare.</param>
@ -46,9 +46,9 @@ namespace System.Net.Http.Formatting
Debug.Assert(stringWithQuality1 != null); Debug.Assert(stringWithQuality1 != null);
Debug.Assert(stringWithQuality2 != null); Debug.Assert(stringWithQuality2 != null);
double quality1 = stringWithQuality1.Quality ?? FormattingUtilities.Match; var quality1 = stringWithQuality1.Quality ?? FormattingUtilities.Match;
double quality2 = stringWithQuality2.Quality ?? FormattingUtilities.Match; var quality2 = stringWithQuality2.Quality ?? FormattingUtilities.Match;
double qualityDifference = quality1 - quality2; var qualityDifference = quality1 - quality2;
if (qualityDifference < 0) if (qualityDifference < 0)
{ {
return -1; return -1;
@ -58,7 +58,7 @@ namespace System.Net.Http.Formatting
return 1; return 1;
} }
if (!String.Equals(stringWithQuality1.Value, stringWithQuality2.Value, StringComparison.OrdinalIgnoreCase)) if (!string.Equals(stringWithQuality1.Value, stringWithQuality2.Value, StringComparison.OrdinalIgnoreCase))
{ {
if (String.Equals(stringWithQuality1.Value, "*", StringComparison.Ordinal)) if (String.Equals(stringWithQuality1.Value, "*", StringComparison.Ordinal))
{ {

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
var i = 0; var i = 0;
while (true) while (true)
{ {
int indexOpen = key.IndexOf('[', i); var indexOpen = key.IndexOf('[', i);
if (indexOpen < 0) if (indexOpen < 0)
{ {
// Fast path, no normalization needed. // Fast path, no normalization needed.

View File

@ -29,7 +29,8 @@ namespace System.Web.Http
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HttpError"/> class containing error message <paramref name="message"/>. /// Initializes a new instance of the <see cref="HttpError"/> class containing error message
/// <paramref name="message"/>.
/// </summary> /// </summary>
/// <param name="message">The error message to associate with this instance.</param> /// <param name="message">The error message to associate with this instance.</param>
public HttpError([NotNull] string message) public HttpError([NotNull] string message)
@ -42,7 +43,9 @@ namespace System.Web.Http
/// Initializes a new instance of the <see cref="HttpError"/> class for <paramref name="exception"/>. /// Initializes a new instance of the <see cref="HttpError"/> class for <paramref name="exception"/>.
/// </summary> /// </summary>
/// <param name="exception">The exception to use for error information.</param> /// <param name="exception">The exception to use for error information.</param>
/// <param name="includeErrorDetail"><c>true</c> to include the exception information in the error; <c>false</c> otherwise</param> /// <param name="includeErrorDetail">
/// <c>true</c> to include the exception information in the error;<c>false</c> otherwise.
/// </param>
public HttpError([NotNull] Exception exception, bool includeErrorDetail) public HttpError([NotNull] Exception exception, bool includeErrorDetail)
: this() : this()
{ {
@ -64,7 +67,9 @@ namespace System.Web.Http
/// Initializes a new instance of the <see cref="HttpError"/> class for <paramref name="modelState"/>. /// Initializes a new instance of the <see cref="HttpError"/> class for <paramref name="modelState"/>.
/// </summary> /// </summary>
/// <param name="modelState">The invalid model state to use for error information.</param> /// <param name="modelState">The invalid model state to use for error information.</param>
/// <param name="includeErrorDetail"><c>true</c> to include exception messages in the error; <c>false</c> otherwise</param> /// <param name="includeErrorDetail">
/// <c>true</c> to include exception messages in the error; <c>false</c> otherwise.
/// </param>
public HttpError([NotNull] ModelStateDictionary modelState, bool includeErrorDetail) public HttpError([NotNull] ModelStateDictionary modelState, bool includeErrorDetail)
: this() : this()
{ {
@ -105,8 +110,9 @@ namespace System.Web.Http
/// <summary> /// <summary>
/// The high-level, user-visible message explaining the cause of the error. Information carried in this field /// The high-level, user-visible message explaining the cause of the error. Information carried in this field
/// should be considered public in that it will go over the wire regardless of the value of error detail policy. /// should be considered public in that it will go over the wire regardless of the value of error detail
/// As a result care should be taken not to disclose sensitive information about the server or the application. /// policy. As a result care should be taken not to disclose sensitive information about the server or the
/// application.
/// </summary> /// </summary>
public string Message public string Message
{ {

View File

@ -20,19 +20,22 @@ namespace System.Net.Http
/// </summary> /// </summary>
public static class HttpRequestMessageExtensions public static class HttpRequestMessageExtensions
{ {
#if !ASPNETCORE50 #if !ASPNETCORE50
/// <summary> /// <summary>
/// Helper method for creating an <see cref="HttpResponseMessage"/> message with a "416 (Requested Range Not Satisfiable)" status code. /// Helper method for creating an <see cref="HttpResponseMessage"/> message with a "416 (Requested Range Not
/// This response can be used in combination with the <see cref="ByteRangeStreamContent"/> to indicate that the requested range or /// Satisfiable)" status code. This response can be used in combination with the
/// ranges do not overlap with the current resource. The response contains a "Content-Range" header indicating the valid upper and lower /// <see cref="ByteRangeStreamContent"/> to indicate that the requested range or
/// bounds for requested ranges. /// ranges do not overlap with the current resource. The response contains a "Content-Range" header indicating
/// the valid upper and lower bounds for requested ranges.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="invalidByteRangeException">An <see cref="InvalidByteRangeException"/> instance, typically thrown by a /// <param name="invalidByteRangeException">An <see cref="InvalidByteRangeException"/> instance, typically
/// <see cref="ByteRangeStreamContent"/> instance.</param> /// thrown by a <see cref="ByteRangeStreamContent"/> instance.</param>
/// <returns>An 416 (Requested Range Not Satisfiable) error response with a Content-Range header indicating the valid range.</returns> /// <returns>
/// An 416 (Requested Range Not Satisfiable) error response with a Content-Range header indicating the valid
/// range.
/// </returns>
public static HttpResponseMessage CreateErrorResponse( public static HttpResponseMessage CreateErrorResponse(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
[NotNull] InvalidByteRangeException invalidByteRangeException) [NotNull] InvalidByteRangeException invalidByteRangeException)
@ -47,9 +50,10 @@ namespace System.Net.Http
#endif #endif
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> representing an error /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/>
/// with an instance of <see cref="ObjectContent{T}"/> wrapping an <see cref="HttpError"/> with message <paramref name="message"/>. /// representing an error with an instance of <see cref="ObjectContent{T}"/> wrapping an
/// If no formatter is found, this method returns a response with status 406 NotAcceptable. /// <see cref="HttpError"/> with message <paramref name="message"/>. If no formatter is found, this method
/// returns a response with status 406 NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method requires that <paramref name="request"/> has been associated with an instance of /// This method requires that <paramref name="request"/> has been associated with an instance of
@ -58,7 +62,10 @@ namespace System.Net.Http
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="message">The error message.</param> /// <param name="message">The error message.</param>
/// <returns>An error response with error message <paramref name="message"/> and status code <paramref name="statusCode"/>.</returns> /// <returns>
/// An error response with error message <paramref name="message"/> and status code
/// <paramref name="statusCode"/>.
/// </returns>
public static HttpResponseMessage CreateErrorResponse( public static HttpResponseMessage CreateErrorResponse(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
HttpStatusCode statusCode, HttpStatusCode statusCode,
@ -68,9 +75,11 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> representing an error /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/>
/// with an instance of <see cref="ObjectContent{T}"/> wrapping an <see cref="HttpError"/> with error message <paramref name="message"/> /// representing an error with an instance of <see cref="ObjectContent{T}"/> wrapping an
/// for exception <paramref name="exception"/>. If no formatter is found, this method returns a response with status 406 NotAcceptable. /// <see cref="HttpError"/> with error message <paramref name="message"/> for exception
/// <paramref name="exception"/>. If no formatter is found, this method returns a response with status 406
/// NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method requires that <paramref name="request"/> has been associated with an instance of /// This method requires that <paramref name="request"/> has been associated with an instance of
@ -93,9 +102,10 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> representing an error /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/>
/// with an instance of <see cref="ObjectContent{T}"/> wrapping an <see cref="HttpError"/> for exception <paramref name="exception"/>. /// representing an error with an instance of <see cref="ObjectContent{T}"/> wrapping an
/// If no formatter is found, this method returns a response with status 406 NotAcceptable. /// <see cref="HttpError"/> for exception <paramref name="exception"/>. If no formatter is found, this method
/// returns a response with status 406 NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method requires that <paramref name="request"/> has been associated with an instance of /// This method requires that <paramref name="request"/> has been associated with an instance of
@ -104,7 +114,9 @@ namespace System.Net.Http
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="exception">The exception.</param> /// <param name="exception">The exception.</param>
/// <returns>An error response for <paramref name="exception"/> with status code <paramref name="statusCode"/>.</returns> /// <returns>
/// An error response for <paramref name="exception"/> with status code <paramref name="statusCode"/>.
/// </returns>
public static HttpResponseMessage CreateErrorResponse( public static HttpResponseMessage CreateErrorResponse(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
HttpStatusCode statusCode, HttpStatusCode statusCode,
@ -114,9 +126,10 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> representing an error /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/>
/// with an instance of <see cref="ObjectContent{T}"/> wrapping an <see cref="HttpError"/> for model state <paramref name="modelState"/>. /// representing an error with an instance of <see cref="ObjectContent{T}"/> wrapping an
/// If no formatter is found, this method returns a response with status 406 NotAcceptable. /// <see cref="HttpError"/> for model state <paramref name="modelState"/>. If no formatter is found, this
/// method returns a response with status 406 NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method requires that <paramref name="request"/> has been associated with an instance of /// This method requires that <paramref name="request"/> has been associated with an instance of
@ -125,7 +138,9 @@ namespace System.Net.Http
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="modelState">The model state.</param> /// <param name="modelState">The model state.</param>
/// <returns>An error response for <paramref name="modelState"/> with status code <paramref name="statusCode"/>.</returns> /// <returns>
/// An error response for <paramref name="modelState"/> with status code <paramref name="statusCode"/>.
/// </returns>
public static HttpResponseMessage CreateErrorResponse( public static HttpResponseMessage CreateErrorResponse(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
HttpStatusCode statusCode, HttpStatusCode statusCode,
@ -135,9 +150,9 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> representing an error /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/>
/// with an instance of <see cref="ObjectContent{T}"/> wrapping <paramref name="error"/> as the content. If no formatter /// representing an error with an instance of <see cref="ObjectContent{T}"/> wrapping <paramref name="error"/>
/// is found, this method returns a response with status 406 NotAcceptable. /// as the content. If no formatter is found, this method returns a response with status 406 NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method requires that <paramref name="request"/> has been associated with an instance of /// This method requires that <paramref name="request"/> has been associated with an instance of
@ -146,7 +161,9 @@ namespace System.Net.Http
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="error">The error to wrap.</param> /// <param name="error">The error to wrap.</param>
/// <returns>An error response wrapping <paramref name="error"/> with status code <paramref name="statusCode"/>.</returns> /// <returns>
/// An error response wrapping <paramref name="error"/> with status code <paramref name="statusCode"/>.
/// </returns>
public static HttpResponseMessage CreateErrorResponse( public static HttpResponseMessage CreateErrorResponse(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
HttpStatusCode statusCode, HttpStatusCode statusCode,
@ -156,9 +173,10 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> with an instance /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> with an
/// of <see cref="ObjectContent{T}"/> as the content and <see cref="System.Net.HttpStatusCode.OK"/> as the status code /// instance of <see cref="ObjectContent{T}"/> as the content and <see cref="System.Net.HttpStatusCode.OK"/>
/// if a formatter can be found. If no formatter is found, this method returns a response with status 406 NotAcceptable. /// as the status code if a formatter can be found. If no formatter is found, this method returns a response
/// with status 406 NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method requires that <paramref name="request"/> has been associated with an instance of /// This method requires that <paramref name="request"/> has been associated with an instance of
@ -167,16 +185,18 @@ namespace System.Net.Http
/// <typeparam name="T">The type of the value.</typeparam> /// <typeparam name="T">The type of the value.</typeparam>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="value">The value to wrap. Can be <c>null</c>.</param> /// <param name="value">The value to wrap. Can be <c>null</c>.</param>
/// <returns>A response wrapping <paramref name="value"/> with <see cref="System.Net.HttpStatusCode.OK"/> status code.</returns> /// <returns>
/// A response wrapping <paramref name="value"/> with <see cref="System.Net.HttpStatusCode.OK"/> status code.
/// </returns>
public static HttpResponseMessage CreateResponse<T>([NotNull] this HttpRequestMessage request, T value) public static HttpResponseMessage CreateResponse<T>([NotNull] this HttpRequestMessage request, T value)
{ {
return request.CreateResponse<T>(HttpStatusCode.OK, value, formatters: null); return request.CreateResponse<T>(HttpStatusCode.OK, value, formatters: null);
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> with an instance /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> with an
/// of <see cref="ObjectContent{T}"/> as the content if a formatter can be found. If no formatter is found, this /// instance of <see cref="ObjectContent{T}"/> as the content if a formatter can be found. If no formatter is
/// method returns a response with status 406 NotAcceptable. /// found, this method returns a response with status 406 NotAcceptable.
/// configuration. /// configuration.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
@ -188,15 +208,18 @@ namespace System.Net.Http
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="value">The value to wrap. Can be <c>null</c>.</param> /// <param name="value">The value to wrap. Can be <c>null</c>.</param>
/// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns> /// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns>
public static HttpResponseMessage CreateResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value) public static HttpResponseMessage CreateResponse<T>(
this HttpRequestMessage request,
HttpStatusCode statusCode,
T value)
{ {
return request.CreateResponse<T>(statusCode, value, formatters: null); return request.CreateResponse<T>(statusCode, value, formatters: null);
} }
/// <summary> /// <summary>
/// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> with an instance /// Helper method that performs content negotiation and creates a <see cref="HttpResponseMessage"/> with an
/// of <see cref="ObjectContent{T}"/> as the content if a formatter can be found. If no formatter is found, this /// instance of <see cref="ObjectContent{T}"/> as the content if a formatter can be found. If no formatter is
/// method returns a response with status 406 NotAcceptable. /// found, this method returns a response with status 406 NotAcceptable.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This method will use the provided <paramref name="configuration"/> or it will get the /// This method will use the provided <paramref name="configuration"/> or it will get the
@ -238,29 +261,39 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/> instance containing the provided /// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/>
/// <paramref name="value"/>. The given <paramref name="mediaType"/> is used to find an instance of <see cref="MediaTypeFormatter"/>. /// instance containing the provided <paramref name="value"/>. The given <paramref name="mediaType"/> is used
/// to find an instance of <see cref="MediaTypeFormatter"/>.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the value.</typeparam> /// <typeparam name="T">The type of the value.</typeparam>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="value">The value to wrap. Can be <c>null</c>.</param> /// <param name="value">The value to wrap. Can be <c>null</c>.</param>
/// <param name="mediaType">The media type used to look up an instance of <see cref="MediaTypeFormatter"/>.</param> /// <param name="mediaType">
/// The media type used to look up an instance of <see cref="MediaTypeFormatter"/>.
/// </param>
/// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns> /// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns>
public static HttpResponseMessage CreateResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value, string mediaType) public static HttpResponseMessage CreateResponse<T>(
this HttpRequestMessage request,
HttpStatusCode statusCode,
T value,
string mediaType)
{ {
return request.CreateResponse(statusCode, value, new MediaTypeHeaderValue(mediaType)); return request.CreateResponse(statusCode, value, new MediaTypeHeaderValue(mediaType));
} }
/// <summary> /// <summary>
/// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/> instance containing the provided /// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/>
/// <paramref name="value"/>. The given <paramref name="mediaType"/> is used to find an instance of <see cref="MediaTypeFormatter"/>. /// instance containing the provided <paramref name="value"/>. The given <paramref name="mediaType"/> is used
/// to find an instance of <see cref="MediaTypeFormatter"/>.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the value.</typeparam> /// <typeparam name="T">The type of the value.</typeparam>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="value">The value to wrap. Can be <c>null</c>.</param> /// <param name="value">The value to wrap. Can be <c>null</c>.</param>
/// <param name="mediaType">The media type used to look up an instance of <see cref="MediaTypeFormatter"/>.</param> /// <param name="mediaType">
/// The media type used to look up an instance of <see cref="MediaTypeFormatter"/>.
/// </param>
/// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns> /// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns>
public static HttpResponseMessage CreateResponse<T>( public static HttpResponseMessage CreateResponse<T>(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
@ -287,8 +320,8 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/> instance containing the provided /// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/>
/// <paramref name="value"/> and the given <paramref name="formatter"/>. /// instance containing the provided <paramref name="value"/> and the given <paramref name="formatter"/>.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the value.</typeparam> /// <typeparam name="T">The type of the value.</typeparam>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
@ -306,15 +339,17 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/> instance containing the provided /// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/>
/// <paramref name="value"/> and the given <paramref name="formatter"/>. /// instance containing the provided <paramref name="value"/> and the given <paramref name="formatter"/>.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the value.</typeparam> /// <typeparam name="T">The type of the value.</typeparam>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="value">The value to wrap. Can be <c>null</c>.</param> /// <param name="value">The value to wrap. Can be <c>null</c>.</param>
/// <param name="formatter">The formatter to use.</param> /// <param name="formatter">The formatter to use.</param>
/// <param name="mediaType">The media type override to set on the response's content. Can be <c>null</c>.</param> /// <param name="mediaType">
/// The media type override to set on the response's content. Can be <c>null</c>.
/// </param>
/// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns> /// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns>
public static HttpResponseMessage CreateResponse<T>( public static HttpResponseMessage CreateResponse<T>(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,
@ -328,15 +363,17 @@ namespace System.Net.Http
} }
/// <summary> /// <summary>
/// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/> instance containing the provided /// Helper method that creates a <see cref="HttpResponseMessage"/> with an <see cref="ObjectContent{T}"/>
/// <paramref name="value"/> and the given <paramref name="formatter"/>. /// instance containing the provided <paramref name="value"/> and the given <paramref name="formatter"/>.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the value.</typeparam> /// <typeparam name="T">The type of the value.</typeparam>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="statusCode">The status code of the created response.</param> /// <param name="statusCode">The status code of the created response.</param>
/// <param name="value">The value to wrap. Can be <c>null</c>.</param> /// <param name="value">The value to wrap. Can be <c>null</c>.</param>
/// <param name="formatter">The formatter to use.</param> /// <param name="formatter">The formatter to use.</param>
/// <param name="mediaType">The media type override to set on the response's content. Can be <c>null</c>.</param> /// <param name="mediaType">
/// The media type override to set on the response's content. Can be <c>null</c>.
/// </param>
/// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns> /// <returns>A response wrapping <paramref name="value"/> with <paramref name="statusCode"/>.</returns>
public static HttpResponseMessage CreateResponse<T>( public static HttpResponseMessage CreateResponse<T>(
[NotNull] this HttpRequestMessage request, [NotNull] this HttpRequestMessage request,

View File

@ -6,9 +6,10 @@ using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Mvc.WebApiCompatShim namespace Microsoft.AspNet.Mvc.WebApiCompatShim
{ {
public class WebApiCompatShimOptionsSetup : IConfigureOptions<MvcOptions>, IConfigureOptions<WebApiCompatShimOptions> public class WebApiCompatShimOptionsSetup
: IConfigureOptions<MvcOptions>, IConfigureOptions<WebApiCompatShimOptions>
{ {
public readonly static string DefaultAreaName = "api"; public static readonly string DefaultAreaName = "api";
public int Order public int Order
{ {

View File

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.Framework.Runtime
{
[AssemblyNeutral]
public interface IAfterCompileContext
{
CSharpCompilation CSharpCompilation { get; set; }
IList<Diagnostic> Diagnostics { get; }
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Framework.Runtime
{
[AssemblyNeutral]
public interface ICompileModule
{
void BeforeCompile(IBeforeCompileContext context);
void AfterCompile(IAfterCompileContext context);
}
}

View File

@ -26,19 +26,19 @@ namespace Microsoft.AspNet.Mvc
{ {
var describe = new ServiceDescriber(configuration); var describe = new ServiceDescriber(configuration);
//
// Options and core services. // Options and core services.
//
yield return describe.Transient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>(); yield return describe.Transient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>();
yield return describe.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>(); yield return describe.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>();
yield return describe.Transient<IAssemblyProvider, DefaultAssemblyProvider>(); yield return describe.Transient<IAssemblyProvider, DefaultAssemblyProvider>();
yield return describe.Transient(typeof(INestedProviderManager<>), typeof(NestedProviderManager<>)); yield return describe.Transient(typeof(INestedProviderManager<>), typeof(NestedProviderManager<>));
yield return describe.Transient(typeof(INestedProviderManagerAsync<>), typeof(NestedProviderManagerAsync<>)); yield return describe.Transient(
typeof(INestedProviderManagerAsync<>),
typeof(NestedProviderManagerAsync<>));
yield return describe.Transient<MvcMarkerService, MvcMarkerService>(); yield return describe.Transient<MvcMarkerService, MvcMarkerService>();
//
// Core action discovery, filters and action execution. // Core action discovery, filters and action execution.
//
// These are consumed only when creating action descriptors, then they can be de-allocated // These are consumed only when creating action descriptors, then they can be de-allocated
yield return describe.Transient<IControllerModelBuilder, DefaultControllerModelBuilder>(); yield return describe.Transient<IControllerModelBuilder, DefaultControllerModelBuilder>();
yield return describe.Transient<IActionModelBuilder, DefaultActionModelBuilder>(); yield return describe.Transient<IActionModelBuilder, DefaultActionModelBuilder>();
@ -74,9 +74,8 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient<INestedProvider<FilterProviderContext>, DefaultFilterProvider>(); yield return describe.Transient<INestedProvider<FilterProviderContext>, DefaultFilterProvider>();
//
// Dataflow - ModelBinding, Validation and Formatting // Dataflow - ModelBinding, Validation and Formatting
//
yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>(); yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
yield return describe.Scoped<IActionBindingContextProvider, DefaultActionBindingContextProvider>(); yield return describe.Scoped<IActionBindingContextProvider, DefaultActionBindingContextProvider>();
@ -93,11 +92,10 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>(); yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>();
yield return describe.Scoped<ICompositeModelValidatorProvider, CompositeModelValidatorProvider>(); yield return describe.Scoped<ICompositeModelValidatorProvider, CompositeModelValidatorProvider>();
yield return describe.Transient<IBodyModelValidator, DefaultBodyModelValidator>(); yield return describe.Transient<IBodyModelValidator, DefaultBodyModelValidator>();
yield return describe.Transient<IValidationExcludeFiltersProvider, DefaultValidationExcludeFiltersProvider>(); yield return describe.Transient<IValidationExcludeFiltersProvider,
DefaultValidationExcludeFiltersProvider>();
//
// Razor, Views and runtime compilation // Razor, Views and runtime compilation
//
// The provider is inexpensive to initialize and provides ViewEngines that may require request // The provider is inexpensive to initialize and provides ViewEngines that may require request
// specific services. // specific services.
@ -135,9 +133,7 @@ namespace Microsoft.AspNet.Mvc
// Virtual path view factory needs to stay scoped so views can get get scoped services. // Virtual path view factory needs to stay scoped so views can get get scoped services.
yield return describe.Scoped<IRazorPageFactory, VirtualPathRazorPageFactory>(); yield return describe.Scoped<IRazorPageFactory, VirtualPathRazorPageFactory>();
//
// View and rendering helpers // View and rendering helpers
//
yield return describe.Transient<IHtmlHelper, HtmlHelper>(); yield return describe.Transient<IHtmlHelper, HtmlHelper>();
yield return describe.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)); yield return describe.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
@ -157,9 +153,7 @@ namespace Microsoft.AspNet.Mvc
DefaultViewComponentInvokerProvider>(); DefaultViewComponentInvokerProvider>();
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>(); yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
//
// Security and Authorization // Security and Authorization
//
yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>(); yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>();
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>(); yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
@ -167,9 +161,7 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider, yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
DefaultAntiForgeryAdditionalDataProvider>(); DefaultAntiForgeryAdditionalDataProvider>();
//
// Api Description // Api Description
//
yield return describe.Singleton<IApiDescriptionGroupCollectionProvider, yield return describe.Singleton<IApiDescriptionGroupCollectionProvider,
ApiDescriptionGroupCollectionProvider>(); ApiDescriptionGroupCollectionProvider>();

View File

@ -48,7 +48,9 @@ namespace Microsoft.AspNet.Mvc
} }
// TODO: KILL THIS // TODO: KILL THIS
private static IServiceProvider BuildFallbackServiceProvider(IEnumerable<IServiceDescriptor> services, IServiceProvider fallback) private static IServiceProvider BuildFallbackServiceProvider(
IEnumerable<IServiceDescriptor> services,
IServiceProvider fallback)
{ {
var sc = HostingServices.Create(fallback); var sc = HostingServices.Create(fallback);
sc.Add(services); sc.Add(services);
@ -58,7 +60,8 @@ namespace Microsoft.AspNet.Mvc
&& t.ServiceType != typeof(IServiceManifest) && t.ServiceType != typeof(IServiceManifest)
&& t.ServiceType != typeof(IServiceProvider)) && t.ServiceType != typeof(IServiceProvider))
.Select(t => t.ServiceType).Distinct(); .Select(t => t.ServiceType).Distinct();
sc.AddInstance<IServiceManifest>(new ServiceManifest(manifestTypes, fallback.GetRequiredService<IServiceManifest>())); sc.AddInstance<IServiceManifest>(
new ServiceManifest(manifestTypes, fallback.GetRequiredService<IServiceManifest>()));
return sc.BuildServiceProvider(); return sc.BuildServiceProvider();
} }
@ -77,22 +80,3 @@ namespace Microsoft.AspNet.Mvc
} }
} }
} }
namespace Microsoft.Framework.Runtime
{
[AssemblyNeutral]
public interface ICompileModule
{
void BeforeCompile(IBeforeCompileContext context);
void AfterCompile(IAfterCompileContext context);
}
[AssemblyNeutral]
public interface IAfterCompileContext
{
CSharpCompilation CSharpCompilation { get; set; }
IList<Diagnostic> Diagnostics { get; }
}
}

View File

@ -994,17 +994,16 @@ namespace Microsoft.AspNet.Mvc.Test
// Assert // Assert
binder.Verify(); binder.Verify();
} }
[Fact] [Fact]
public async Task TryUpdateModel_PredicateOverload_UsesPassedArguments() public async Task TryUpdateModel_PredicateOverload_UsesPassedArguments()
{ {
// Arrange // Arrange
var modelName = "mymodel"; var modelName = "mymodel";
Func<ModelBindingContext, string, bool> includePredicate = Func<ModelBindingContext, string, bool> includePredicate = (context, propertyName) =>
(context, propertyName) => string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) ||
string.Equals(propertyName, "include1", StringComparison.OrdinalIgnoreCase) || string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase);
string.Equals(propertyName, "include2", StringComparison.OrdinalIgnoreCase);
var binder = new Mock<IModelBinder>(); var binder = new Mock<IModelBinder>();
var valueProvider = Mock.Of<IValueProvider>(); var valueProvider = Mock.Of<IValueProvider>();

View File

@ -227,7 +227,7 @@ namespace Microsoft.AspNet.Mvc
var viewEngine = new Mock<IViewEngine>(MockBehavior.Strict); var viewEngine = new Mock<IViewEngine>(MockBehavior.Strict);
viewEngine.Setup(e => e.FindPartialView(It.IsAny<ActionContext>(), It.IsAny<string>())) viewEngine.Setup(e => e.FindPartialView(It.IsAny<ActionContext>(), It.IsAny<string>()))
.Returns(ViewEngineResult.NotFound( .Returns(ViewEngineResult.NotFound(
"Components/Object/some-view", "Components/Object/some-view",
new[] { "view-location1", "view-location2" })) new[] { "view-location1", "view-location2" }))
.Verifiable(); .Verifiable();

View File

@ -1056,7 +1056,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert // Assert
var user = JsonConvert.DeserializeObject<User>(response); var user = JsonConvert.DeserializeObject<User>(response);
// Should not update any not explicitly mentioned properties. // Should not update any not explicitly mentioned properties.
Assert.NotEqual("SomeName", user.UserName); Assert.NotEqual("SomeName", user.UserName);
Assert.NotEqual(123, user.Key); Assert.NotEqual(123, user.Key);
@ -1079,7 +1079,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert // Assert
var user = JsonConvert.DeserializeObject<User>(response); var user = JsonConvert.DeserializeObject<User>(response);
// Should not update any not explicitly mentioned properties. // Should not update any not explicitly mentioned properties.
Assert.Equal("SomeName", user.UserName); Assert.Equal("SomeName", user.UserName);
Assert.Equal(123, user.Key); Assert.Equal(123, user.Key);

View File

@ -10,13 +10,20 @@ namespace System.Net.Http.Formatting
/// </summary> /// </summary>
internal static class MediaTypeConstants internal static class MediaTypeConstants
{ {
private static readonly MediaTypeHeaderValue _defaultApplicationXmlMediaType = new MediaTypeHeaderValue("application/xml"); private static readonly MediaTypeHeaderValue _defaultApplicationXmlMediaType =
private static readonly MediaTypeHeaderValue _defaultTextXmlMediaType = new MediaTypeHeaderValue("text/xml"); new MediaTypeHeaderValue("application/xml");
private static readonly MediaTypeHeaderValue _defaultApplicationJsonMediaType = new MediaTypeHeaderValue("application/json"); private static readonly MediaTypeHeaderValue _defaultTextXmlMediaType =
private static readonly MediaTypeHeaderValue _defaultTextJsonMediaType = new MediaTypeHeaderValue("text/json"); new MediaTypeHeaderValue("text/xml");
private static readonly MediaTypeHeaderValue _defaultApplicationOctetStreamMediaType = new MediaTypeHeaderValue("application/octet-stream"); private static readonly MediaTypeHeaderValue _defaultApplicationJsonMediaType =
private static readonly MediaTypeHeaderValue _defaultApplicationFormUrlEncodedMediaType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); new MediaTypeHeaderValue("application/json");
private static readonly MediaTypeHeaderValue _defaultApplicationBsonMediaType = new MediaTypeHeaderValue("application/bson"); private static readonly MediaTypeHeaderValue _defaultTextJsonMediaType =
new MediaTypeHeaderValue("text/json");
private static readonly MediaTypeHeaderValue _defaultApplicationOctetStreamMediaType =
new MediaTypeHeaderValue("application/octet-stream");
private static readonly MediaTypeHeaderValue _defaultApplicationFormUrlEncodedMediaType =
new MediaTypeHeaderValue("application/x-www-form-urlencoded");
private static readonly MediaTypeHeaderValue _defaultApplicationBsonMediaType =
new MediaTypeHeaderValue("application/bson");
/// <summary> /// <summary>
/// Gets a <see cref="MediaTypeHeaderValue"/> instance representing <c>application/octet-stream</c>. /// Gets a <see cref="MediaTypeHeaderValue"/> instance representing <c>application/octet-stream</c>.

View File

@ -44,7 +44,7 @@ namespace ModelBindingWebSite.Controllers
} }
// User_FromForm has a FromForm property. // User_FromForm has a FromForm property.
public User_FromForm MultipleFromFormParameterAndProperty(User_FromForm user, public User_FromForm MultipleFromFormParameterAndProperty(User_FromForm user,
[FromForm] Address defaultAddress) [FromForm] Address defaultAddress)
{ {
user.HomeAddress = defaultAddress; user.HomeAddress = defaultAddress;

View File

@ -5,7 +5,7 @@ namespace ModelBindingWebSite
{ {
public class Department public class Department
{ {
// A single property marked with a binder metadata attribute makes it a binder metadata poco. // A single property marked with a binder metadata attribute makes it a binder metadata poco.
[FromTest] [FromTest]
public string Name { get; set; } public string Name { get; set; }
} }

View File

@ -16,7 +16,7 @@ namespace ModelBindingWebSite
[FromQuery] [FromQuery]
public Address ShippingAddress { get; set; } public Address ShippingAddress { get; set; }
// Should get it from the first value provider which // Should get it from the first value provider which
// can provide values for this. // can provide values for this.
public Address DefaultAddress { get; set; } public Address DefaultAddress { get; set; }
} }