Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote-tracking branch 'upstream/master'

* upstream/master: (68 commits)
  Fix for test broken during prior commit rebase.
  26: Separate service location from dependency injection
  Update .gitattributes for .resx to merge=union
  Remove MediaTypeFormatterCollection.Find() methods. They were not being used and they did not take into account whether a formatters supported a particular type.
  Issue #12 Add CreateResponse<T>() overloads that accept formatter and media type parameters.
  Performance improvement on validate. Cache expensive parts of the modelbinding context across requests, specifically validation nodes. Also need to ensure the cached nodes get propagated down to usage point when we clone a context.
  Mark quota exceptions as Handled for Json
  Setting /nr:false for build.cmd, will stop MSBUILD.exe from sticking around after builds are finished.
  Fix race condition in TaskHelpersExtensions.Catch
  349089: Fixing the issue where HttpMethodConstraint does not work for WebAPI on Web Host
  Update DNOA packages in Microsoft.Web.WebPages.OAuth project to released version.
  perf: improve TaskHelpers.Iterate. There's a huge perf penalty for switch threads on completed tasks.
  [cleanup] remove empty folder from project no functional changes.
  Added support for dealing with wildcard matching in accept headers by updating the comparison mechanism by which we compare two media types. The comparison now includes wild-cards as part of it matching algorithm (both "*/*" and "text/*".
  Fix additional collection-related APIs to consume/return consistent types
  Bug 333326: HttpControllerDispatcher should not set the controllerName on HttpControllerDescriptor based on controller route value
  DevDiv 388456 -- WebHost should not use Transfer-Encoding chunked when content length is known
  DevDiv bug 388519 --[Monitoring]  HttpActionBindingTracer was not created, and tracing did not show the roll-up of model binding results.
  Minor code clean up in cookie related classes.
  Updated BufferedMediaTypeFormatter to follow the pattern defined by MediaTypeFormatterTestBase with respect to when to close the inner stream, how to handle 0 size content-length, and other constraints. At the same time allowed the common "using" pattern for reading and writing streams so that a sample formatter written on top of BufferedMediaTypeFormatter simply can do this:
  ...
  • Loading branch information...
commit 1a87c8af1bf47958b94b8267192afd9f4666d78f 2 parents 4152f54 + 2d768a9
@grendello grendello authored
Showing with 7,128 additions and 2,649 deletions.
  1. +42 −0 .gitattributes
  2. +2 −2 build.cmd
  3. +1 −1  src/Common/TaskHelpers.cs
  4. +32 −11 src/Common/TaskHelpersExtensions.cs
  5. +1 −0  src/Microsoft.Web.Http.Data.EntityFramework/Metadata/LinqToEntitiesTypeDescriptor.cs
  6. +1 −1  src/Microsoft.Web.Http.Data.EntityFramework/Microsoft.Web.Http.Data.EntityFramework.csproj
  7. +1 −1  src/Microsoft.Web.Http.Data.EntityFramework/packages.config
  8. +4 −0 src/Microsoft.Web.Mvc/Resources/HttpRequestBaseExtensions.cs
  9. +13 −21 src/Microsoft.Web.WebPages.OAuth/Microsoft.Web.WebPages.OAuth.csproj
  10. +6 −6 src/Microsoft.Web.WebPages.OAuth/packages.config
  11. +37 −31 src/System.Net.Http.Formatting/Formatting/BufferedMediaTypeFormatter.cs
  12. +8 −125 src/System.Net.Http.Formatting/Formatting/FormDataCollection.cs
  13. +8 −13 src/System.Net.Http.Formatting/Formatting/JsonMediaTypeFormatter.cs
  14. +1 −1  src/System.Net.Http.Formatting/Formatting/MediaRangeMapping.cs
  15. +26 −11 src/System.Net.Http.Formatting/Formatting/MediaTypeFormatter.cs
  16. +45 −19 src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterCollection.cs
  17. +0 −46 src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterExtensions.cs
  18. +0 −79 src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueEqualityComparer.cs
  19. +38 −11 src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueExtensions.cs
  20. +8 −8 src/System.Net.Http.Formatting/Formatting/MediaTypeWithQualityHeaderValueComparer.cs
  21. +9 −2 src/System.Net.Http.Formatting/Formatting/SecureJsonTextReader.cs
  22. +1 −1  src/System.Net.Http.Formatting/Formatting/XmlMediaTypeFormatter.cs
  23. +56 −0 src/System.Net.Http.Formatting/FormattingUtilities.cs
  24. +1 −0  src/System.Net.Http.Formatting/GlobalSuppressions.cs
  25. +300 −0 src/System.Net.Http.Formatting/Headers/CookieHeaderValue.cs
  26. +127 −0 src/System.Net.Http.Formatting/Headers/CookieState.cs
  27. +3 −3 src/System.Net.Http.Formatting/HttpContentExtensions.cs
  28. +58 −0 src/System.Net.Http.Formatting/HttpRequestHeadersExtensions.cs
  29. +57 −0 src/System.Net.Http.Formatting/HttpResponseHeadersExtensions.cs
  30. +115 −0 src/System.Net.Http.Formatting/Internal/HttpValueCollection.cs
  31. +18 −0 src/System.Net.Http.Formatting/Properties/Resources.Designer.cs
  32. +6 −0 src/System.Net.Http.Formatting/Properties/Resources.resx
  33. +6 −3 src/System.Net.Http.Formatting/System.Net.Http.Formatting.csproj
  34. +1 −1  src/System.Web.Helpers/ServerInfo.cs
  35. BIN  src/System.Web.Helpers/WebGrid/_WebGridRenderer.generated.cs
  36. +1 −0  src/System.Web.Http.SelfHost/GlobalSuppressions.cs
  37. +35 −0 src/System.Web.Http.SelfHost/HttpRequestMessageExtensions.cs
  38. +2 −8 src/System.Web.Http.SelfHost/HttpSelfHostServer.cs
  39. +1 −0  src/System.Web.Http.SelfHost/System.Web.Http.SelfHost.csproj
  40. +2 −1  src/System.Web.Http.WebHost/GlobalConfiguration.cs
  41. +24 −17 src/System.Web.Http.WebHost/HttpControllerHandler.cs
  42. +4 −3 src/{System.Web.Http/Dispatcher → System.Web.Http.WebHost}/HttpControllerTypeCacheSerializer.cs
  43. +9 −0 src/System.Web.Http.WebHost/Properties/SRResources.Designer.cs
  44. +3 −0  src/System.Web.Http.WebHost/Properties/SRResources.resx
  45. +29 −0 src/System.Web.Http.WebHost/Routing/HttpContextBaseExtensions.cs
  46. +35 −0 src/System.Web.Http.WebHost/Routing/HttpWebRoute.cs
  47. +6 −1 src/System.Web.Http.WebHost/System.Web.Http.WebHost.csproj
  48. +23 −0 src/System.Web.Http.WebHost/WebHostAssembliesResolver.cs
  49. +0 −62 src/System.Web.Http.WebHost/WebHostBuildManager.cs
  50. +89 −0 src/System.Web.Http.WebHost/WebHostHttpControllerTypeResolver.cs
  51. +1 −1  src/System.Web.Http/ApiController.cs
  52. +61 −14 src/System.Web.Http/Controllers/ApiControllerActionSelector.cs
  53. +1 −1  src/System.Web.Http/Controllers/HttpActionBinding.cs
  54. +3 −3 src/System.Web.Http/Controllers/HttpActionContextExtensions.cs
  55. +1 −1  src/System.Web.Http/Controllers/HttpActionDescriptor.cs
  56. +3 −2 src/System.Web.Http/Controllers/HttpControllerConfigurationAttribute.cs
  57. +0 −2  src/System.Web.Http/Controllers/HttpControllerContext.cs
  58. +46 −7 src/System.Web.Http/Controllers/HttpControllerDescriptor.cs
  59. +8 −0 src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs
  60. +38 −0 src/System.Web.Http/Dependencies/EmptyResolver.cs
  61. +19 −0 src/System.Web.Http/Dependencies/IDependencyResolver.cs
  62. +27 −0 src/System.Web.Http/Dependencies/IDependencyScope.cs
  63. +6 −7 src/System.Web.Http/Description/ApiExplorer.cs
  64. +22 −0 src/System.Web.Http/Dispatcher/DefaultAssembliesResolver.cs
  65. +0 −60 src/System.Web.Http/Dispatcher/DefaultBuildManager.cs
  66. +43 −23 src/System.Web.Http/Dispatcher/DefaultHttpControllerActivator.cs
  67. +45 −56 src/System.Web.Http/Dispatcher/{DefaultHttpControllerFactory.cs → DefaultHttpControllerSelector.cs}
  68. +71 −0 src/System.Web.Http/Dispatcher/DefaultHttpControllerTypeResolver.cs
  69. +17 −15 src/System.Web.Http/Dispatcher/HttpControllerDispatcher.cs
  70. +9 −24 src/System.Web.Http/Dispatcher/HttpControllerTypeCache.cs
  71. +0 −102 src/System.Web.Http/Dispatcher/HttpControllerTypeCacheUtil.cs
  72. +20 −0 src/System.Web.Http/Dispatcher/IAssembliesResolver.cs
  73. +0 −48 src/System.Web.Http/Dispatcher/IBuildManager.cs
  74. +5 −2 src/System.Web.Http/Dispatcher/IHttpControllerActivator.cs
  75. +0 −35 src/System.Web.Http/Dispatcher/IHttpControllerFactory.cs
  76. +28 −0 src/System.Web.Http/Dispatcher/IHttpControllerSelector.cs
  77. +19 −0 src/System.Web.Http/Dispatcher/IHttpControllerTypeResolver.cs
  78. +2 −0  src/System.Web.Http/GlobalSuppressions.cs
  79. +5 −0 src/System.Web.Http/Hosting/HttpPropertyKeys.cs
  80. +25 −12 src/System.Web.Http/HttpConfiguration.cs
  81. +148 −10 src/System.Web.Http/HttpRequestMessageExtensions.cs
  82. +3 −3 src/System.Web.Http/HttpServer.cs
  83. +5 −0 src/System.Web.Http/Internal/TypeDescriptorHelper.cs
  84. +6 −0 src/System.Web.Http/ModelBinding/Binders/CompositeModelBinder.cs
  85. +1 −1  src/System.Web.Http/ModelBinding/Binders/CompositeModelBinderProvider.cs
  86. +1 −1  src/System.Web.Http/ModelBinding/DefaultActionValueBinder.cs
  87. +3 −3 src/System.Web.Http/ModelBinding/FormDataCollectionExtensions.cs
  88. +10 −12 src/System.Web.Http/ModelBinding/ModelBinderAttribute.cs
  89. +36 −8 src/System.Web.Http/ModelBinding/ModelBinderParameterBinding.cs
  90. +2 −1  src/System.Web.Http/Properties/AssemblyInfo.cs
  91. +28 −28 src/System.Web.Http/Properties/SRResources.Designer.cs
  92. +8 −8 src/System.Web.Http/Properties/SRResources.resx
  93. +57 −0 src/System.Web.Http/Routing/MediaTypeFormatterExtensions.cs
  94. +26 −25 src/{System.Net.Http.Formatting/Formatting → System.Web.Http/Routing}/UriPathExtensionMapping.cs
  95. +0 −150 src/System.Web.Http/Services/DefaultServiceResolver.cs
  96. +597 −0 src/System.Web.Http/Services/DefaultServices.cs
  97. +0 −254 src/System.Web.Http/Services/DependencyResolver.cs
  98. +0 −22 src/System.Web.Http/Services/IDependencyResolver.cs
  99. +53 −51 src/System.Web.Http/{DependencyResolverExtensions.cs → ServicesExtensions.cs}
  100. +15 −11 src/System.Web.Http/System.Web.Http.csproj
  101. +3 −5 src/System.Web.Http/Tracing/ITraceManager.cs
  102. +19 −19 src/System.Web.Http/Tracing/TraceManager.cs
  103. +6 −2 src/System.Web.Http/Tracing/Tracers/ActionValueBinderTracer.cs
  104. +12 −0 src/System.Web.Http/Tracing/Tracers/HttpActionBindingTracer.cs
  105. +26 −4 src/System.Web.Http/Tracing/Tracers/HttpControllerActivatorTracer.cs
  106. +16 −27 src/System.Web.Http/Tracing/Tracers/{HttpControllerFactoryTracer.cs → HttpControllerDescriptorTracer.cs}
  107. +67 −0 src/System.Web.Http/Tracing/Tracers/HttpControllerSelectorTracer.cs
  108. +15 −6 src/System.Web.Http/Tracing/Tracers/MediaTypeFormatterTracer.cs
  109. +29 −7 src/System.Web.Http/Validation/DefaultBodyModelValidator.cs
  110. +12 −1 src/System.Web.Http/Validation/ModelValidationNode.cs
  111. +6 −0 src/System.Web.Http/Validation/ModelValidationRequiredMemberSelector.cs
  112. +9 −0 src/System.Web.Http/ValueProviders/Providers/NameValueCollectionValueProvider.cs
  113. +6 −1 src/System.Web.Http/ValueProviders/Providers/QueryStringValueProviderFactory.cs
  114. +5 −4 src/System.Web.Http/ValueProviders/Providers/RouteDataValueProviderFactory.cs
  115. +2 −0  src/System.Web.Mvc/AcceptVerbsAttribute.cs
  116. +6 −0 src/System.Web.Mvc/HtmlHelper.cs
  117. +15 −0 src/System.Web.Mvc/HttpHeadAttribute.cs
  118. +15 −0 src/System.Web.Mvc/HttpOptionsAttribute.cs
  119. +15 −0 src/System.Web.Mvc/HttpPatchAttribute.cs
  120. +3 −1 src/System.Web.Mvc/HttpVerbs.cs
  121. +2 −2 src/System.Web.Mvc/Properties/MvcResources.Designer.cs
  122. +1 −1  src/System.Web.Mvc/Properties/MvcResources.resx
  123. +3 −0  src/System.Web.Mvc/System.Web.Mvc.csproj
  124. +10 −2 src/System.Web.Razor/Parser/CSharpCodeParser.Statements.cs
  125. +25 −13 src/System.Web.Razor/Parser/HtmlMarkupParser.Document.cs
  126. +3 −9 src/System.Web.Razor/Parser/HtmlMarkupParser.Section.cs
  127. +1 −1  test/Microsoft.Web.Http.Data.Test/Microsoft.Web.Http.Data.Test.csproj
  128. +1 −0  test/Microsoft.Web.Http.Data.Test/Models/CatalogEntities.cs
  129. +1 −1  test/Microsoft.Web.Http.Data.Test/packages.config
  130. +1 −1  test/System.Net.Http.Formatting.Test.Integration/JsonNetSerializationTest.cs
  131. +5 −9 test/System.Net.Http.Formatting.Test.Integration/JsonNetValidationTest.cs
  132. +0 −2  test/System.Net.Http.Formatting.Test.Unit/DataSets/HttpUnitTestDataSets.cs
  133. +1 −8 test/System.Net.Http.Formatting.Test.Unit/DataSets/Types/HttpTestData.cs
  134. +137 −35 test/System.Net.Http.Formatting.Test.Unit/Formatting/BufferedMediaTypeFormatterTests.cs
  135. +14 −0 test/System.Net.Http.Formatting.Test.Unit/Formatting/DataContractJsonMediaTypeFormatterTests.cs
  136. +14 −0 test/System.Net.Http.Formatting.Test.Unit/Formatting/JsonMediaTypeFormatterTests.cs
  137. +0 −16 test/System.Net.Http.Formatting.Test.Unit/Formatting/MediaTypeFormatterExtensionsTests.cs
  138. +16 −7 test/System.Net.Http.Formatting.Test.Unit/Formatting/MediaTypeFormatterTestBase.cs
  139. +86 −2 test/System.Net.Http.Formatting.Test.Unit/Formatting/MediaTypeFormatterTests.cs
  140. +0 −176 test/System.Net.Http.Formatting.Test.Unit/Formatting/MediaTypeHeadeValueExtensionsTests.cs
  141. +0 −199 test/System.Net.Http.Formatting.Test.Unit/Formatting/MediaTypeHeaderValueEqualityComparerTests.cs
  142. +165 −0 test/System.Net.Http.Formatting.Test.Unit/Formatting/MediaTypeHeaderValueExtensionsTests.cs
  143. +425 −0 test/System.Net.Http.Formatting.Test.Unit/Formatting/SerializerConsistencyTests.cs
  144. +17 −0 test/System.Net.Http.Formatting.Test.Unit/Formatting/XmlMediaTypeFormatterTests.cs
  145. +17 −0 test/System.Net.Http.Formatting.Test.Unit/Formatting/XmlSerializerMediaTypeFormatterTests.cs
  146. +150 −1 test/System.Net.Http.Formatting.Test.Unit/FormattingUtilitiesTests.cs
  147. +137 −0 test/System.Net.Http.Formatting.Test.Unit/Headers/CookieHeaderValueTest.cs
  148. +132 −0 test/System.Net.Http.Formatting.Test.Unit/Headers/CookieStateTest.cs
  149. +94 −6 test/System.Net.Http.Formatting.Test.Unit/HttpContentExtensionsTest.cs
  150. +57 −0 test/System.Net.Http.Formatting.Test.Unit/HttpRequestHeadersExtensionsTest.cs
  151. +62 −0 test/System.Net.Http.Formatting.Test.Unit/HttpResponseHeadersExtensionsTest.cs
  152. +136 −0 test/System.Net.Http.Formatting.Test.Unit/Internal/HttpValueCollectionTest.cs
  153. +7 −3 test/System.Net.Http.Formatting.Test.Unit/System.Net.Http.Formatting.Test.Unit.csproj
  154. +1 −1  test/System.Web.Helpers.Test/ServerInfoTest.cs
  155. +6 −6 test/System.Web.Http.Integration.Test/ApiExplorer/ApiExplorerSettingsTest.cs
  156. +7 −7 test/System.Web.Http.Integration.Test/ApiExplorer/DocumentationTest.cs
  157. +6 −6 test/System.Web.Http.Integration.Test/ApiExplorer/FormattersTest.cs
  158. +9 −9 test/System.Web.Http.Integration.Test/ApiExplorer/ParameterSourceTest.cs
  159. +9 −9 test/System.Web.Http.Integration.Test/ApiExplorer/RouteConstraintsTest.cs
  160. +20 −20 test/System.Web.Http.Integration.Test/ApiExplorer/RoutesTest.cs
  161. +2 −2 test/System.Web.Http.Integration.Test/Authentication/CustomMessageHandler.cs
  162. +1 −1  test/System.Web.Http.Integration.Test/ContentNegotiation/DefaultContentNegotiatorTests.cs
  163. +19 −12 ...Http.Integration.Test/Controllers/{CustomControllerFactoryTest.cs → CustomControllerDescriptorTest.cs}
  164. +1 −1  test/System.Web.Http.Integration.Test/ExceptionHandling/HttpResponseExceptionTest.cs
  165. +3 −2 test/System.Web.Http.Integration.Test/ModelBinding/BodyBindingTests.cs
  166. +6 −3 test/System.Web.Http.Integration.Test/ModelBinding/DefaultActionValueBinderTest.cs
  167. +2 −1  test/System.Web.Http.Integration.Test/ModelBinding/HttpContentBindingTests.cs
  168. +1 −1  test/System.Web.Http.Integration.Test/System.Web.Http.Integration.Test.csproj
  169. +3 −3 test/System.Web.Http.Integration.Test/Util/ApiExplorerHelper.cs
  170. +57 −0 test/System.Web.Http.SelfHost.Test/DeeplyNestedTypeTests.cs
  171. +2 −0  test/System.Web.Http.SelfHost.Test/System.Web.Http.SelfHost.Test.csproj
  172. +20 −20 test/System.Web.Http.Test/Controllers/ApiControllerTest.cs
  173. +30 −2 test/System.Web.Http.Test/Controllers/HttpConfigurationTest.cs
  174. +33 −0 test/System.Web.Http.Test/Dispatcher/DefaultAssembliesResolverTest.cs
  175. +0 −73 test/System.Web.Http.Test/Dispatcher/DefaultBuildManagerTest.cs
  176. +121 −0 test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerActivatorTest.cs
  177. +316 −0 test/System.Web.Http.Test/Dispatcher/DefaultHttpControllerSelectorTest.cs
  178. +176 −15 test/System.Web.Http.Test/HttpRequestMessageExtensionsTest.cs
  179. +1 −1  test/System.Web.Http.Test/ModelBinding/Binders/ArrayModelBinderTest.cs
  180. +6 −6 test/System.Web.Http.Test/ModelBinding/Binders/CollectionModelBinderTest.cs
  181. +4 −2 test/System.Web.Http.Test/ModelBinding/Binders/ComplexModelDtoModelBinderTest.cs
  182. +1 −1  test/System.Web.Http.Test/ModelBinding/Binders/DictionaryModelBinderTest.cs
  183. +6 −4 test/System.Web.Http.Test/ModelBinding/Binders/KeyValuePairModelBinderTest.cs
  184. +2 −2 test/System.Web.Http.Test/ModelBinding/Binders/KeyValuePairModelBinderUtilTest.cs
  185. +1 −1  test/System.Web.Http.Test/ModelBinding/Binders/MutableObjectModelBinderTest.cs
  186. +1 −1  test/System.Web.Http.Test/ModelBinding/DefaultActionValueBinderTest.cs
  187. +29 −6 test/System.Web.Http.Test/ModelBinding/ModelBinderAttributeTest.cs
  188. +4 −2 test/System.Web.Http.Test/QueryableAttributeTest.cs
  189. +50 −0 test/System.Web.Http.Test/Routing/MediaTypeFormatterExtensionsTests.cs
  190. +25 −47 ...t.Http.Formatting.Test.Unit/Formatting → System.Web.Http.Test/Routing}/UriPathExtensionMappingTests.cs
  191. +735 −0 test/System.Web.Http.Test/Services/DefaultServicesTests.cs
  192. +0 −219 test/System.Web.Http.Test/Services/DependencyResolverTests.cs
  193. +15 −7 test/System.Web.Http.Test/System.Web.Http.Test.csproj
  194. +10 −10 test/System.Web.Http.Test/Tracing/TraceManagerTest.cs
  195. +29 −0 test/System.Web.Http.Test/Tracing/Tracers/ActionValueBinderTracerTest.cs
  196. +11 −11 test/System.Web.Http.Test/Tracing/Tracers/HttpControllerActivatorTracerTest.cs
  197. +126 −0 test/System.Web.Http.Test/Tracing/Tracers/HttpControllerDescriptorTracerTest.cs
  198. +0 −63 test/System.Web.Http.Test/Tracing/Tracers/HttpControllerFactoryTracerTest.cs
  199. +65 −0 test/System.Web.Http.Test/Tracing/Tracers/HttpControllerSelectorTracerTest.cs
  200. +86 −3 test/System.Web.Http.Test/Tracing/Tracers/MediaTypeFormatterTracerTest.cs
  201. +1 −1  test/System.Web.Http.Test/Validation/ModelValidationRequiredMemberSelectorTest.cs
  202. +29 −0 test/System.Web.Http.Test/ValueProviders/Providers/QueryStringValueProviderFactoryTest.cs
  203. +29 −0 test/System.Web.Http.Test/ValueProviders/Providers/RouteDataValueProviderFactoryTest.cs
  204. +57 −0 test/System.Web.Http.WebHost.Test/HttpControllerHandlerTest.cs
  205. +4 −0 test/System.Web.Http.WebHost.Test/System.Web.Http.WebHost.Test.csproj
  206. +2 −0  test/System.Web.Mvc.Test/System.Web.Mvc.Test.csproj
  207. +3 −3 test/System.Web.Mvc.Test/Test/HtmlHelperTest.cs
  208. +25 −0 test/System.Web.Mvc.Test/Test/HttpHeadAttributeTest.cs
  209. +25 −0 test/System.Web.Mvc.Test/Test/HttpOptionsAttributeTest.cs
  210. +24 −0 test/System.Web.Mvc.Test/Test/HttpPatchAttributeTest.cs
  211. +20 −0 test/System.Web.Razor.Test/Parser/CSharp/CSharpErrorTest.cs
  212. +1 −1  test/System.Web.Razor.Test/Parser/CSharp/CSharpSectionTest.cs
  213. +21 −0 test/System.Web.Razor.Test/Parser/Html/HtmlDocumentTest.cs
  214. +3 −1 test/System.Web.WebPages.Razor.Test/System.Web.WebPages.Razor.Test.csproj
View
42 .gitattributes
@@ -0,0 +1,42 @@
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
+
+*.bmp binary
+*.gif binary
+*.jpg binary
+*.png binary
+
+*.ascx text
+*.cmd text
+*.coffee text
+*.config text
+*.cs text diff=csharp
+*.csproj text merge=union
+*.css text
+*.cshtml text
+*.htm text
+*.html text
+*.htm text
+*.js text
+*.msbuild text
+*.resx text merge=union
+*.ruleset text
+*.Stylecop text
+*.targets text
+*.tt text
+*.txt text
+*.vb text
+*.vbhtml text
+*.vbproj text merge=union
+*.xml text
+*.xunit text
+
+*.sln text eol=crlf merge=union
View
4 build.cmd
@@ -7,12 +7,12 @@ mkdir bin
:Build
if "%1" == "" goto BuildDefaults
-%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild Runtime.msbuild /m /t:%* /v:M /fl /flp:LogFile=bin\msbuild.log;Verbosity=Normal
+%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild Runtime.msbuild /m /nr:false /t:%* /v:M /fl /flp:LogFile=bin\msbuild.log;Verbosity=Normal
if errorlevel 1 goto BuildFail
goto BuildSuccess
:BuildDefaults
-%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild Runtime.msbuild /m /v:M /fl /flp:LogFile=bin\msbuild.log;Verbosity=Normal
+%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\msbuild Runtime.msbuild /m /nr:false /v:M /fl /flp:LogFile=bin\msbuild.log;Verbosity=Normal
if errorlevel 1 goto BuildFail
goto BuildSuccess
View
2  src/Common/TaskHelpers.cs
@@ -404,7 +404,7 @@ private static void RunNextCallback(object state)
RunNext(engine);
break;
}
- });
+ }, TaskContinuationOptions.ExecuteSynchronously);
}
else
{
View
43 src/Common/TaskHelpersExtensions.cs
@@ -21,6 +21,12 @@ internal static class TaskHelpersExtensions
/// </summary>
internal static Task Catch(this Task task, Func<CatchInfo, CatchInfo.CatchResult> continuation, CancellationToken cancellationToken = default(CancellationToken))
{
+ // Fast path for successful tasks, to prevent an extra TCS allocation
+ if (task.Status == TaskStatus.RanToCompletion)
+ {
+ return task;
+ }
+
return task.CatchImpl(() => continuation(new CatchInfo(task)).Task.ToTask<AsyncVoid>(), cancellationToken);
}
@@ -35,6 +41,12 @@ internal static Task Catch(this Task task, Func<CatchInfo, CatchInfo.CatchResult
/// </summary>
internal static Task<TResult> Catch<TResult>(this Task<TResult> task, Func<CatchInfo<TResult>, CatchInfo<TResult>.CatchResult> continuation, CancellationToken cancellationToken = default(CancellationToken))
{
+ // Fast path for successful tasks, to prevent an extra TCS allocation
+ if (task.Status == TaskStatus.RanToCompletion)
+ {
+ return task;
+ }
+
return task.CatchImpl(() => continuation(new CatchInfo<TResult>(task)).Task, cancellationToken);
}
@@ -230,37 +242,46 @@ internal static Task<TResult> FastUnwrap<TResult>(this Task<Task<TResult>> task)
/// Calls the given continuation, after the given task has completed, regardless of the state
/// the task ended in. Intended to roughly emulate C# 5's support for "finally" in async methods.
/// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The caught exception type is reflected into a faulted task.")]
internal static Task Finally(this Task task, Action continuation)
{
- return task.FinallyImpl<AsyncVoid>(continuation);
+ // Stay on the same thread if we can
+ if (task.IsCompleted)
+ {
+ try
+ {
+ continuation();
+ return task;
+ }
+ catch (Exception ex)
+ {
+ return TaskHelpers.FromError(ex);
+ }
+ }
+
+ // Split into a continuation method so that we don't create a closure unnecessarily
+ return FinallyImplContinuation<AsyncVoid>(task, continuation);
}
/// <summary>
/// Calls the given continuation, after the given task has completed, regardless of the state
/// the task ended in. Intended to roughly emulate C# 5's support for "finally" in async methods.
/// </summary>
- internal static Task<TResult> Finally<TResult>(this Task<TResult> task, Action continuation)
- {
- return task.FinallyImpl<TResult>(continuation);
- }
-
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The caught exception type is reflected into a faulted task.")]
- private static Task<TResult> FinallyImpl<TResult>(this Task task, Action continuation)
+ internal static Task<TResult> Finally<TResult>(this Task<TResult> task, Action continuation)
{
// Stay on the same thread if we can
if (task.IsCompleted)
{
- TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
try
{
continuation();
- tcs.TrySetFromTask(task);
+ return task;
}
catch (Exception ex)
{
- tcs.TrySetException(ex);
+ return TaskHelpers.FromError<TResult>(ex);
}
- return tcs.Task;
}
// Split into a continuation method so that we don't create a closure unnecessarily
View
1  src/Microsoft.Web.Http.Data.EntityFramework/Metadata/LinqToEntitiesTypeDescriptor.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Metadata.Edm;
using System.Data.Objects.DataClasses;
View
2  src/Microsoft.Web.Http.Data.EntityFramework/Microsoft.Web.Http.Data.EntityFramework.csproj
@@ -46,7 +46,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="EntityFramework">
- <HintPath>..\..\packages\EntityFramework.4.1.10331.0\lib\EntityFramework.dll</HintPath>
+ <HintPath>..\..\packages\EntityFramework.5.0.0-beta2\lib\net40\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
View
2  src/Microsoft.Web.Http.Data.EntityFramework/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="EntityFramework" version="4.1.10331.0" />
+ <package id="EntityFramework" version="5.0.0-beta2" />
<package id="Microsoft.Net.Http" version="2.0.20326.1" />
</packages>
View
4 src/Microsoft.Web.Mvc/Resources/HttpRequestBaseExtensions.cs
@@ -58,6 +58,10 @@ public static bool IsHttpMethod(this HttpRequestBase request, HttpVerbs httpMeth
return request.IsHttpMethod("DELETE", allowOverride);
case HttpVerbs.Head:
return request.IsHttpMethod("HEAD", allowOverride);
+ case HttpVerbs.Patch:
+ return request.IsHttpMethod("PATCH", allowOverride);
+ case HttpVerbs.Options:
+ return request.IsHttpMethod("OPTIONS", allowOverride);
default:
// CODEREVIEW: does this look reasonable?
return request.IsHttpMethod(httpMethod.ToString().ToUpperInvariant(), allowOverride);
View
34 src/Microsoft.Web.WebPages.OAuth/Microsoft.Web.WebPages.OAuth.csproj
@@ -43,29 +43,23 @@
<CodeAnalysisDictionary Include="..\CodeAnalysisDictionary.xml" />
</ItemGroup>
<ItemGroup>
- <Reference Include="DotNetOpenAuth.AspNet, Version=4.0.0.12065, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\packages\DotNetOpenAuth.AspNet.4.0.0-RC1\lib\net40-full\DotNetOpenAuth.AspNet.dll</HintPath>
+ <Reference Include="DotNetOpenAuth.AspNet, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\DotNetOpenAuth.AspNet.4.0.0.12084\lib\net40-full\DotNetOpenAuth.AspNet.dll</HintPath>
</Reference>
- <Reference Include="DotNetOpenAuth.Core, Version=4.0.0.12065, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\packages\DotNetOpenAuth.Core.4.0.0-RC1\lib\net40-full\DotNetOpenAuth.Core.dll</HintPath>
+ <Reference Include="DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\DotNetOpenAuth.Core.4.0.0.12084\lib\net40-full\DotNetOpenAuth.Core.dll</HintPath>
</Reference>
- <Reference Include="DotNetOpenAuth.OAuth, Version=4.0.0.12065, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\packages\DotNetOpenAuth.OAuth.Core.4.0.0-RC1\lib\net40-full\DotNetOpenAuth.OAuth.dll</HintPath>
+ <Reference Include="DotNetOpenAuth.OAuth, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\DotNetOpenAuth.OAuth.Core.4.0.0.12084\lib\net40-full\DotNetOpenAuth.OAuth.dll</HintPath>
</Reference>
- <Reference Include="DotNetOpenAuth.OAuth.Consumer, Version=4.0.0.12065, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\packages\DotNetOpenAuth.OAuth.Consumer.4.0.0-RC1\lib\net40-full\DotNetOpenAuth.OAuth.Consumer.dll</HintPath>
+ <Reference Include="DotNetOpenAuth.OAuth.Consumer, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\DotNetOpenAuth.OAuth.Consumer.4.0.0.12084\lib\net40-full\DotNetOpenAuth.OAuth.Consumer.dll</HintPath>
</Reference>
- <Reference Include="DotNetOpenAuth.OpenId, Version=4.0.0.12065, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\packages\DotNetOpenAuth.OpenId.Core.4.0.0-RC1\lib\net40-full\DotNetOpenAuth.OpenId.dll</HintPath>
+ <Reference Include="DotNetOpenAuth.OpenId, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\DotNetOpenAuth.OpenId.Core.4.0.0.12084\lib\net40-full\DotNetOpenAuth.OpenId.dll</HintPath>
</Reference>
- <Reference Include="DotNetOpenAuth.OpenId.RelyingParty, Version=4.0.0.12065, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\packages\DotNetOpenAuth.OpenId.RelyingParty.4.0.0-RC1\lib\net40-full\DotNetOpenAuth.OpenId.RelyingParty.dll</HintPath>
+ <Reference Include="DotNetOpenAuth.OpenId.RelyingParty, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\DotNetOpenAuth.OpenId.RelyingParty.4.0.0.12084\lib\net40-full\DotNetOpenAuth.OpenId.RelyingParty.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@@ -115,9 +109,7 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
- <None Include="packages.config">
- <SubType>Designer</SubType>
- </None>
+ <None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
12 src/Microsoft.Web.WebPages.OAuth/packages.config
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="DotNetOpenAuth.AspNet" version="4.0.0-RC1" />
- <package id="DotNetOpenAuth.Core" version="4.0.0-RC1" />
- <package id="DotNetOpenAuth.OAuth.Consumer" version="4.0.0-RC1" />
- <package id="DotNetOpenAuth.OAuth.Core" version="4.0.0-RC1" />
- <package id="DotNetOpenAuth.OpenId.Core" version="4.0.0-RC1" />
- <package id="DotNetOpenAuth.OpenId.RelyingParty" version="4.0.0-RC1" />
+ <package id="DotNetOpenAuth.AspNet" version="4.0.0.12084" />
+ <package id="DotNetOpenAuth.Core" version="4.0.0.12084" />
+ <package id="DotNetOpenAuth.OAuth.Consumer" version="4.0.0.12084" />
+ <package id="DotNetOpenAuth.OAuth.Core" version="4.0.0.12084" />
+ <package id="DotNetOpenAuth.OpenId.Core" version="4.0.0.12084" />
+ <package id="DotNetOpenAuth.OpenId.RelyingParty" version="4.0.0.12084" />
</packages>
View
68 src/System.Net.Http.Formatting/Formatting/BufferedMediaTypeFormatter.cs
@@ -1,35 +1,35 @@
-using System.IO;
+using System.Diagnostics.Contracts;
+using System.IO;
using System.Net.Http.Headers;
+using System.Net.Http.Internal;
using System.Threading.Tasks;
+using System.Web.Http;
namespace System.Net.Http.Formatting
{
/// <summary>
- /// Helper class to allow a synchronous formatter on top of the async formatter infrastructure.
- /// This does not guarantee non-blocking threads. The only way to guarantee that we don't block a thread on IO is:
- /// a) use the async form, or
- /// b) fully buffer the entire write operation.
- /// The user opted out of the async form, meaning they can tolerate potential thread blockages.
- /// This class just tries to do smart buffering to minimize that blockage.
- /// It also gives us a place to do future optimizations on synchronous usage.
+ /// Base class for writing a synchronous formatter on top of the asynchronous formatter infrastructure.
+ /// This does not guarantee non-blocking threads. The only way to guarantee that we don't block a thread on IO is
+ /// to use the asynchronous <see cref="MediaTypeFormatter"/>.
/// </summary>
public abstract class BufferedMediaTypeFormatter : MediaTypeFormatter
{
+ private const int MinBufferSize = 0;
private const int DefaultBufferSize = 16 * 1024;
private int _bufferSizeInBytes = DefaultBufferSize;
/// <summary>
- /// Suggested size of buffer to use with streams, in bytes.
+ /// Suggested size of buffer to use with streams, in bytes. The default size is 16K.
/// </summary>
public int BufferSize
{
get { return _bufferSizeInBytes; }
set
{
- if (value < 0)
+ if (value < MinBufferSize)
{
- throw new ArgumentOutOfRangeException("value");
+ throw Error.ArgumentGreaterThanOrEqualTo("value", value, MinBufferSize);
}
_bufferSizeInBytes = value;
}
@@ -38,10 +38,14 @@ public int BufferSize
/// <summary>
/// Writes synchronously to the buffered stream.
/// </summary>
+ /// <remarks>
+ /// An implementation of this method should close <paramref name="stream"/> upon completion.
+ /// </remarks>
/// <param name="type">The type of the object to write.</param>
/// <param name="value">The object value to write. It may be <c>null</c>.</param>
/// <param name="stream">The <see cref="Stream"/> to which to write.</param>
- /// <param name="contentHeaders">The <see cref="HttpContentHeaders"/> if available. It may be <c>null</c>.</param>
+ /// <param name="contentHeaders">The <see cref="HttpContentHeaders"/> if available. Note that
+ /// modifying the headers will have no effect on the generated HTTP message; they should only be used to guide the writing.</param>
public virtual void WriteToStream(Type type, object value, Stream stream, HttpContentHeaders contentHeaders)
{
throw new NotSupportedException(RS.Format(Properties.Resources.MediaTypeFormatterCannotWriteSync, GetType().Name));
@@ -50,9 +54,12 @@ public virtual void WriteToStream(Type type, object value, Stream stream, HttpCo
/// <summary>
/// Reads synchronously from the buffered stream.
/// </summary>
+ /// <remarks>
+ /// An implementation of this method should close <paramref name="stream"/> upon completion.
+ /// </remarks>
/// <param name="type">The type of the object to deserialize.</param>
/// <param name="stream">The <see cref="Stream"/> to read.</param>
- /// <param name="contentHeaders">The <see cref="HttpContentHeaders"/> if available. It may be <c>null</c>.</param>
+ /// <param name="contentHeaders">The <see cref="HttpContentHeaders"/> if available.</param>
/// <param name="formatterLogger">The <see cref="IFormatterLogger"/> to log events to.</param>
/// <returns>An object of the given type.</returns>
public virtual object ReadFromStream(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
@@ -73,22 +80,13 @@ public sealed override Task WriteToStreamAsync(Type type, object value, Stream s
throw new ArgumentNullException("stream");
}
- // Underlying stream will do encoding into separate sections. This is just buffering.
return TaskHelpers.RunSynchronously(
() =>
{
- Stream bufferedStream = GetBufferStream(stream);
-
- try
+ using (Stream bufferedStream = GetBufferStream(stream, _bufferSizeInBytes))
{
WriteToStream(type, value, bufferedStream, contentHeaders);
}
- finally
- {
- // Disposing the bufferStream will dispose the underlying stream.
- // So Flush any remaining bytes that have been written, but don't actually close the stream.
- bufferedStream.Flush();
- }
});
}
@@ -104,27 +102,35 @@ public sealed override Task<object> ReadFromStreamAsync(Type type, Stream stream
throw new ArgumentNullException("stream");
}
- // See explanation in OnWriteToStreamAsync.
return TaskHelpers.RunSynchronously<object>(
() =>
{
- // When using a buffered read, the buffer really owns the underlying stream because it's whole purpose
- // is to eagerly read bytes from the underlying stream.
- // This means this reader can't cooperate with other readers (in the same way that writers can).
- // So when this reader is done, we close the stream to prevent subsequent readers from getting random bytes.
- using (Stream bufferedStream = GetBufferStream(stream))
+ if (contentHeaders != null && contentHeaders.ContentLength == 0)
+ {
+ return GetDefaultValueForType(type);
+ }
+
+ using (Stream bufferedStream = GetBufferStream(stream, _bufferSizeInBytes))
{
return ReadFromStream(type, bufferedStream, contentHeaders, formatterLogger);
}
});
}
- private Stream GetBufferStream(Stream inner)
+ private static Stream GetBufferStream(Stream innerStream, int bufferSize)
{
+ Contract.Assert(innerStream != null);
+
+ // We wrap the inner stream in a non-closing delegating stream so that we allow the user
+ // to use the using (...) pattern yet not break the contract of formatters not closing
+ // the inner stream.
+ Stream nonClosingStream = new NonClosingDelegatingStream(innerStream);
+
// This uses a naive buffering. BufferedStream() will block the thread while it drains the buffer.
// We can explore a smarter implementation that async drains the buffer.
- Stream bufferedStream = new BufferedStream(inner, _bufferSizeInBytes);
+ Stream bufferedStream = new BufferedStream(nonClosingStream, bufferSize);
+ // We now have buffered, non-closing stream which we can pass to the user.
return bufferedStream;
}
}
View
133 src/System.Net.Http.Formatting/Formatting/FormDataCollection.cs
@@ -2,14 +2,12 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
+using System.Net.Http.Formatting.Internal;
using System.Net.Http.Formatting.Parsers;
-using System.Net.Http.Internal;
-using System.Runtime.Serialization;
-using System.Text;
using System.Threading;
namespace System.Net.Http.Formatting
-{
+{
/// <summary>
/// Represent the form data.
/// - This has 100% fidelity (including ordering, which is important for deserializing ordered array).
@@ -20,13 +18,13 @@ public class FormDataCollection : IEnumerable<KeyValuePair<string, string>>
{
private readonly IEnumerable<KeyValuePair<string, string>> _pairs;
private NameValueCollection _nameValueCollection;
-
+
/// <summary>
/// Initialize a form collection around incoming data.
/// The key value enumeration should be immutable.
/// </summary>
/// <param name="pairs">incoming set of key value pairs. Ordering is preserved.</param>
- [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the convention for representing FormData")]
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is the convention for representing FormData")]
public FormDataCollection(IEnumerable<KeyValuePair<string, string>> pairs)
{
if (pairs == null)
@@ -35,7 +33,7 @@ public FormDataCollection(IEnumerable<KeyValuePair<string, string>> pairs)
}
_pairs = pairs;
}
-
+
/// <summary>
/// Initialize a form collection from a query string.
/// Uri and FormURl body have the same schema.
@@ -90,19 +88,19 @@ public FormDataCollection(string query)
return result;
}
-
+
/// <summary>
/// Get the collection as a NameValueCollection.
/// Beware this loses some ordering. Values are ordered within a key,
/// but keys are no longer ordered against each other.
/// </summary>
public NameValueCollection ReadAsNameValueCollection()
- {
+ {
if (_nameValueCollection == null)
{
// Initialize in a private collection to be thread-safe, and swap the finished object.
// Ok to double initialize this.
- NameValueCollection newCollection = HttpValueCollection.Build(this);
+ NameValueCollection newCollection = HttpValueCollection.Create(this);
Interlocked.Exchange(ref _nameValueCollection, newCollection);
}
return _nameValueCollection;
@@ -134,120 +132,5 @@ IEnumerator IEnumerable.GetEnumerator()
IEnumerable ie = _pairs;
return ie.GetEnumerator();
}
-
- // NameValueCollection to represent FormData, has a useful ToString method.
- [Serializable]
- private class HttpValueCollection : NameValueCollection
- {
- private HttpValueCollection()
- : base(StringComparer.Ordinal) // case-sensitive keys
- {
- }
-
- // Use a builder function instead of a ctor to avoid virtual calls from the ctor.
- public static NameValueCollection Build(IEnumerable<KeyValuePair<string, string>> pairs)
- {
- var nvc = new HttpValueCollection();
-
- // Ordering example:
- // k=A&j=B&k=C --> k:[A,C];j=[B].
- foreach (KeyValuePair<string, string> kv in pairs)
- {
- string key = kv.Key;
- if (key == null)
- {
- key = string.Empty;
- }
- string value = kv.Value;
- if (value == null)
- {
- value = string.Empty;
- }
- nvc.Add(key, value);
- }
-
- nvc.IsReadOnly = false;
- return nvc;
- }
-
- protected HttpValueCollection(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- }
-
- public override string ToString()
- {
- return ToString(true);
- }
-
- private string ToString(bool urlencoded)
- {
- int n = Count;
- if (n == 0)
- {
- return String.Empty;
- }
-
- StringBuilder s = new StringBuilder();
- string key, keyPrefix, item;
-
- for (int i = 0; i < n; i++)
- {
- key = GetKey(i);
-
- if (urlencoded)
- {
- key = UriQueryUtility.UrlEncode(key);
- }
-
- keyPrefix = (!String.IsNullOrEmpty(key)) ? (key + "=") : String.Empty;
-
- ArrayList values = (ArrayList)BaseGet(i);
- int numValues = (values != null) ? values.Count : 0;
-
- if (s.Length > 0)
- {
- s.Append('&');
- }
-
- if (numValues == 1)
- {
- s.Append(keyPrefix);
- item = (string)values[0];
- if (urlencoded)
- {
- item = UriQueryUtility.UrlEncode(item);
- }
-
- s.Append(item);
- }
- else if (numValues == 0)
- {
- s.Append(keyPrefix);
- }
- else
- {
- for (int j = 0; j < numValues; j++)
- {
- if (j > 0)
- {
- s.Append('&');
- }
-
- s.Append(keyPrefix);
- item = (string)values[j];
- if (urlencoded)
- {
- item = UriQueryUtility.UrlEncode(item);
- }
-
- s.Append(item);
- }
- }
- }
-
- return s.ToString();
- }
- }
}
}
View
21 src/System.Net.Http.Formatting/Formatting/JsonMediaTypeFormatter.cs
@@ -252,21 +252,13 @@ public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpC
JsonSerializer jsonSerializer = JsonSerializer.Create(_jsonSerializerSettings);
if (formatterLogger != null)
{
+ // Error must always be marked as handled
+ // Failure to do so can cause the exception to be rethrown at every recursive level and overflow the stack for x64 CLR processes
jsonSerializer.Error += (sender, e) =>
{
Exception exception = e.ErrorContext.Error;
-
- // reader quota exceptions are fatal and cannot be recovered from
- // we need to shortcircuit any further deserialization
- if (exception is JsonReaderQuotaException)
- {
- e.ErrorContext.Handled = false;
- }
- else
- {
- formatterLogger.LogError(e.ErrorContext.Path, exception.Message);
- e.ErrorContext.Handled = true;
- }
+ formatterLogger.LogError(e.ErrorContext.Path, exception.Message);
+ e.ErrorContext.Handled = true;
};
}
return jsonSerializer.Deserialize(jsonTextReader, type);
@@ -333,7 +325,10 @@ public override Task WriteToStreamAsync(Type type, object value, Stream stream,
{
if (MediaTypeFormatter.TryGetDelegatingTypeForIQueryableGenericOrSame(ref type))
{
- value = MediaTypeFormatter.GetTypeRemappingConstructor(type).Invoke(new object[] { value });
+ if (value != null)
+ {
+ value = MediaTypeFormatter.GetTypeRemappingConstructor(type).Invoke(new object[] { value });
+ }
}
DataContractJsonSerializer dataContractSerializer = GetDataContractSerializer(type);
View
2  src/System.Net.Http.Formatting/Formatting/MediaRangeMapping.cs
@@ -62,7 +62,7 @@ public override double TryMatchMediaType(HttpRequestMessage request)
{
foreach (MediaTypeWithQualityHeaderValue mediaType in acceptHeader)
{
- if (mediaType != null && MediaTypeHeaderValueEqualityComparer.EqualityComparer.Equals(MediaRange, mediaType))
+ if (MediaRange.IsSubsetOf(mediaType))
{
return mediaType.Quality.HasValue ? mediaType.Quality.Value : MediaTypeMatch.Match;
}
View
37 src/System.Net.Http.Formatting/Formatting/MediaTypeFormatter.cs
@@ -157,6 +157,7 @@ protected Encoding SelectCharacterEncoding(HttpContentHeaders contentHeaders)
Encoding encoding = null;
if (contentHeaders != null && contentHeaders.ContentType != null)
{
+ // Find encoding based on content type charset parameter
string charset = contentHeaders.ContentType.CharSet;
if (!String.IsNullOrWhiteSpace(charset))
{
@@ -168,6 +169,8 @@ protected Encoding SelectCharacterEncoding(HttpContentHeaders contentHeaders)
if (encoding == null)
{
+ // We didn't find a character encoding match based on the content headers.
+ // Instead we try getting the default character encoding.
encoding = SupportedEncodings.FirstOrDefault();
}
@@ -264,12 +267,8 @@ internal ResponseMediaTypeMatch SelectResponseMediaType(Type type, HttpRequestMe
ResponseFormatterSelectionResult.MatchOnRequestWithMediaTypeMapping);
}
- // Sort accept headers in descending order based on q factor.
- IEnumerable<MediaTypeWithQualityHeaderValue> acceptHeaderMediaTypes =
- request.Headers.Accept.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer);
-
// Match against the accept header.
- if (TryMatchSupportedMediaType(acceptHeaderMediaTypes, out mediaTypeMatch))
+ if (TryMatchSupportedMediaType(request, out mediaTypeMatch))
{
mediaTypeMatch.SetEncoding(characterEncodingMatch);
return new ResponseMediaTypeMatch(
@@ -334,11 +333,11 @@ internal Encoding SelectResponseCharacterEncoding(HttpRequestMessage request)
internal bool TryMatchSupportedMediaType(MediaTypeHeaderValue mediaType, out MediaTypeMatch mediaTypeMatch)
{
- Contract.Assert(mediaType != null, "mediaType cannot be null.");
+ Contract.Assert(mediaType != null);
foreach (MediaTypeHeaderValue supportedMediaType in SupportedMediaTypes)
{
- if (MediaTypeHeaderValueEqualityComparer.EqualityComparer.Equals(supportedMediaType, mediaType))
+ if (supportedMediaType.IsSubsetOf(mediaType))
{
// If the incoming media type had an associated quality factor, propagate it to the match
MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue = mediaType as MediaTypeWithQualityHeaderValue;
@@ -355,12 +354,17 @@ internal bool TryMatchSupportedMediaType(MediaTypeHeaderValue mediaType, out Med
return false;
}
- internal bool TryMatchSupportedMediaType(IEnumerable<MediaTypeHeaderValue> mediaTypes, out MediaTypeMatch mediaTypeMatch)
+ internal bool TryMatchSupportedMediaType(HttpRequestMessage request, out MediaTypeMatch mediaTypeMatch)
{
- Contract.Assert(mediaTypes != null, "mediaTypes cannot be null.");
- foreach (MediaTypeHeaderValue mediaType in mediaTypes)
+ Contract.Assert(request != null);
+
+ // Sort accept headers in descending order based on q factor.
+ IEnumerable<MediaTypeWithQualityHeaderValue> acceptMediaTypeValues =
+ request.Headers.Accept.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer);
+
+ foreach (MediaTypeHeaderValue acceptMediaTypeValue in acceptMediaTypeValues)
{
- if (TryMatchSupportedMediaType(mediaType, out mediaTypeMatch))
+ if (TryMatchSupportedMediaType(acceptMediaTypeValue, out mediaTypeMatch))
{
return true;
}
@@ -422,6 +426,7 @@ public virtual void SetDefaultContentHeaders(Type type, HttpContentHeaders heade
headers.ContentType = parsedMediaType;
}
+ // If content type is not set then set it based on supported media types.
if (headers.ContentType == null)
{
MediaTypeHeaderValue defaultMediaType = SupportedMediaTypes.FirstOrDefault();
@@ -430,6 +435,16 @@ public virtual void SetDefaultContentHeaders(Type type, HttpContentHeaders heade
headers.ContentType = defaultMediaType.Clone();
}
}
+
+ // If content type charset parameter is not set then set it based on the supported encodings.
+ if (headers.ContentType != null && headers.ContentType.CharSet == null)
+ {
+ Encoding defaultEncoding = SupportedEncodings.FirstOrDefault();
+ if (defaultEncoding != null)
+ {
+ headers.ContentType.CharSet = defaultEncoding.WebName;
+ }
+ }
}
/// <summary>
View
64 src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterCollection.cs
@@ -2,6 +2,9 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http.Headers;
+using System.Web.Http;
+using System.Xml;
+using System.Xml.Linq;
namespace System.Net.Http.Formatting
{
@@ -57,23 +60,6 @@ public FormUrlEncodedMediaTypeFormatter FormUrlEncodedFormatter
get { return Items.OfType<FormUrlEncodedMediaTypeFormatter>().FirstOrDefault(); }
}
- public MediaTypeFormatter Find(string mediaType)
- {
- MediaTypeHeaderValue val = MediaTypeHeaderValue.Parse(mediaType);
- return Find(val);
- }
-
- /// <summary>
- /// Find a formatter in this collection that matches the requested media type.
- /// </summary>
- /// <returns>Returns a formatter or null if not found.</returns>
- public MediaTypeFormatter Find(MediaTypeHeaderValue mediaType)
- {
- var comparer = MediaTypeHeaderValueEqualityComparer.EqualityComparer;
- MediaTypeFormatter formatter = Items.FirstOrDefault(f => f.SupportedMediaTypes.Any(mt => comparer.Equals(mt, mediaType)));
- return formatter;
- }
-
/// <summary>
/// Helper to search a collection for a formatter that can read the .NET type in the given mediaType.
/// </summary>
@@ -84,11 +70,11 @@ public MediaTypeFormatter FindReader(Type type, MediaTypeHeaderValue mediaType)
{
if (type == null)
{
- throw new ArgumentNullException("type");
+ throw Error.ArgumentNull("type");
}
if (mediaType == null)
{
- throw new ArgumentNullException("mediaType");
+ throw Error.ArgumentNull("mediaType");
}
foreach (MediaTypeFormatter formatter in this.Items)
@@ -103,6 +89,46 @@ public MediaTypeFormatter FindReader(Type type, MediaTypeHeaderValue mediaType)
}
/// <summary>
+ /// Helper to search a collection for a formatter that can write the .NET type in the given mediaType.
+ /// </summary>
+ /// <param name="type">.NET type to read</param>
+ /// <param name="mediaType">media type to match on.</param>
+ /// <returns>Formatter that can write the type. Null if no formatter found.</returns>
+ public MediaTypeFormatter FindWriter(Type type, MediaTypeHeaderValue mediaType)
+ {
+ if (type == null)
+ {
+ throw Error.ArgumentNull("type");
+ }
+ if (mediaType == null)
+ {
+ throw Error.ArgumentNull("mediaType");
+ }
+
+ foreach (MediaTypeFormatter formatter in Items)
+ {
+ MediaTypeHeaderValue match;
+ if (formatter.CanWriteAs(type, mediaType, out match))
+ {
+ return formatter;
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Returns true if the type is one of those loosely defined types that should be excluded from validation
+ /// </summary>
+ /// <param name="type">.NET <see cref="Type"/> to validate</param>
+ /// <returns><c>true</c> if the type should be excluded.</returns>
+ public static bool IsTypeExcludedFromValidation(Type type)
+ {
+ return FormattingUtilities.IsJTokenType(type) || typeof(XObject).IsAssignableFrom(type) || typeof(XmlNode).IsAssignableFrom(type)
+ || typeof(FormDataCollection).IsAssignableFrom(type);
+ }
+
+ /// <summary>
/// Creates a collection of new instances of the default <see cref="MediaTypeFormatter"/>s.
/// </summary>
/// <returns>The collection of default <see cref="MediaTypeFormatter"/> instances.</returns>
View
46 src/System.Net.Http.Formatting/Formatting/MediaTypeFormatterExtensions.cs
@@ -1,5 +1,4 @@
using System.ComponentModel;
-using System.Diagnostics.CodeAnalysis;
using System.Net.Http.Headers;
namespace System.Net.Http.Formatting
@@ -64,51 +63,6 @@ public static class MediaTypeFormatterExtensions
/// <summary>
/// Updates the given <paramref name="formatter"/>'s set of <see cref="MediaTypeMapping"/> elements
- /// so that it associates the <paramref name="mediaType"/> with <see cref="Uri"/>s ending with
- /// the given <paramref name="uriPathExtension"/>.
- /// </summary>
- /// <param name="formatter">The <see cref="MediaTypeFormatter"/> to receive the new <see cref="UriPathExtensionMapping"/> item.</param>
- /// <param name="uriPathExtension">The string of the <see cref="Uri"/> path extension.</param>
- /// <param name="mediaType">The <see cref="MediaTypeHeaderValue"/> to associate with <see cref="Uri"/>s
- /// ending with <paramref name="uriPathExtension"/>.</param>
- [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "There is no meaningful System.Uri representation for a path suffix such as '.xml'")]
- public static void AddUriPathExtensionMapping(
- this MediaTypeFormatter formatter,
- string uriPathExtension,
- MediaTypeHeaderValue mediaType)
- {
- if (formatter == null)
- {
- throw new ArgumentNullException("formatter");
- }
-
- UriPathExtensionMapping mapping = new UriPathExtensionMapping(uriPathExtension, mediaType);
- formatter.MediaTypeMappings.Add(mapping);
- }
-
- /// <summary>
- /// Updates the given <paramref name="formatter"/>'s set of <see cref="MediaTypeMapping"/> elements
- /// so that it associates the <paramref name="mediaType"/> with <see cref="Uri"/>s ending with
- /// the given <paramref name="uriPathExtension"/>.
- /// </summary>
- /// <param name="formatter">The <see cref="MediaTypeFormatter"/> to receive the new <see cref="UriPathExtensionMapping"/> item.</param>
- /// <param name="uriPathExtension">The string of the <see cref="Uri"/> path extension.</param>
- /// <param name="mediaType">The string media type to associate with <see cref="Uri"/>s
- /// ending with <paramref name="uriPathExtension"/>.</param>
- [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "There is no meaningful System.Uri representation for a path suffix such as '.xml'")]
- public static void AddUriPathExtensionMapping(this MediaTypeFormatter formatter, string uriPathExtension, string mediaType)
- {
- if (formatter == null)
- {
- throw new ArgumentNullException("formatter");
- }
-
- UriPathExtensionMapping mapping = new UriPathExtensionMapping(uriPathExtension, mediaType);
- formatter.MediaTypeMappings.Add(mapping);
- }
-
- /// <summary>
- /// Updates the given <paramref name="formatter"/>'s set of <see cref="MediaTypeMapping"/> elements
/// so that it associates the <paramref name="mediaType"/> with requests or responses containing
/// <paramref name="mediaRange"/> in the content headers.
/// </summary>
View
79 src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueEqualityComparer.cs
@@ -1,79 +0,0 @@
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Diagnostics.Contracts;
-using System.Linq;
-using System.Net.Http.Headers;
-
-namespace System.Net.Http.Formatting
-{
- /// <summary>
- /// Provides a special <see cref="MediaTypeHeaderValue"/> comparer function
- /// </summary>
- internal class MediaTypeHeaderValueEqualityComparer : IEqualityComparer<MediaTypeHeaderValue>
- {
- private static readonly MediaTypeHeaderValueEqualityComparer _mediaTypeEqualityComparer = new MediaTypeHeaderValueEqualityComparer();
-
- private MediaTypeHeaderValueEqualityComparer()
- {
- }
-
- /// <summary>
- /// Gets the equality comparer.
- /// </summary>
- public static MediaTypeHeaderValueEqualityComparer EqualityComparer
- {
- get { return _mediaTypeEqualityComparer; }
- }
-
- /// <summary>
- /// 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 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
- /// and match those of <paramref name="mediaType2"/> then it is a match even though <paramref name="mediaType2"/> may have additional
- /// parameters.
- /// </summary>
- /// <param name="mediaType1">The first media type.</param>
- /// <param name="mediaType2">The second media type.</param>
- /// <returns><c>true</c> if the two media types are considered equal based on the algorithm above.</returns>
- [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is part of implementing IEqualityComparer.")]
- public bool Equals(MediaTypeHeaderValue mediaType1, MediaTypeHeaderValue mediaType2)
- {
- Contract.Assert(mediaType1 != null, "The 'mediaType1' parameter should not be null.");
- Contract.Assert(mediaType2 != null, "The 'mediaType2' parameter should not be null.");
-
- if (!String.Equals(mediaType1.MediaType, mediaType2.MediaType, StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- foreach (NameValueHeaderValue parameter1 in mediaType1.Parameters)
- {
- if (mediaType2.Parameters.FirstOrDefault(
- (parameter2) =>
- {
- return
- String.Equals(parameter1.Name, parameter2.Name, StringComparison.OrdinalIgnoreCase) &&
- String.Equals(parameter1.Value, parameter2.Value, StringComparison.OrdinalIgnoreCase);
- }) == null)
- {
- return false;
- }
- }
-
- return true;
- }
-
- /// <summary>
- /// Returns a hash code for this instance.
- /// </summary>
- /// <param name="mediaType">Type of the media.</param>
- /// <returns>
- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- /// </returns>
- public int GetHashCode(MediaTypeHeaderValue mediaType)
- {
- return mediaType.MediaType.ToUpperInvariant().GetHashCode();
- }
- }
-}
View
49 src/System.Net.Http.Formatting/Formatting/MediaTypeHeaderValueExtensions.cs
@@ -1,4 +1,5 @@
using System.Diagnostics.Contracts;
+using System.Linq;
using System.Net.Http.Headers;
namespace System.Net.Http.Formatting
@@ -14,26 +15,52 @@ public static bool IsMediaRange(this MediaTypeHeaderValue mediaType)
return new ParsedMediaTypeHeaderValue(mediaType).IsSubTypeMediaRange;
}
- public static bool IsWithinMediaRange(this MediaTypeHeaderValue mediaType, MediaTypeHeaderValue mediaRange)
+ /// <summary>
+ /// 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 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
+ /// and match those of <paramref name="mediaType2"/> then it is a match even though <paramref name="mediaType2"/> may have additional
+ /// parameters.
+ /// </summary>
+ /// <param name="mediaType1">The first media type.</param>
+ /// <param name="mediaType2">The second media type.</param>
+ /// <returns><c>true</c> if this is a superset of <paramref name="mediaType2"/>; false otherwise.</returns>
+ public static bool IsSubsetOf(this MediaTypeHeaderValue mediaType1, MediaTypeHeaderValue mediaType2)
{
- Contract.Assert(mediaType != null, "The 'mediaType' parameter should not be null.");
- Contract.Assert(mediaRange != null, "The 'mediaRange' parameter should not be null.");
+ Contract.Assert(mediaType1 != null);
+
+ if (mediaType2 == null)
+ {
+ return false;
+ }
- ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
- ParsedMediaTypeHeaderValue parsedMediaRange = new ParsedMediaTypeHeaderValue(mediaRange);
+ ParsedMediaTypeHeaderValue parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
+ ParsedMediaTypeHeaderValue parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
- if (!String.Equals(parsedMediaType.Type, parsedMediaRange.Type, StringComparison.OrdinalIgnoreCase))
+ if (!String.Equals(parsedMediaType1.Type, parsedMediaType2.Type, StringComparison.OrdinalIgnoreCase))
{
- return parsedMediaRange.IsAllMediaRange;
+ if (!parsedMediaType2.IsAllMediaRange)
+ {
+ return false;
+ }
}
- else if (!String.Equals(parsedMediaType.SubType, parsedMediaRange.SubType, StringComparison.OrdinalIgnoreCase))
+ else if (!String.Equals(parsedMediaType1.SubType, parsedMediaType2.SubType, StringComparison.OrdinalIgnoreCase))
{
- return parsedMediaRange.IsSubTypeMediaRange;
+ if (!parsedMediaType2.IsSubTypeMediaRange)
+ {
+ return false;
+ }
}
- if (!String.IsNullOrWhiteSpace(parsedMediaRange.CharSet))
+ // 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
+ foreach (NameValueHeaderValue parameter1 in mediaType1.Parameters)
{
- return String.Equals(parsedMediaRange.CharSet, parsedMediaType.CharSet, StringComparison.OrdinalIgnoreCase);
+ if (!mediaType2.Parameters.Any((parameter2) => { return parameter1.Equals(parameter2); }))
+ {
+ return false;
+ }
}
return true;
View
16 src/System.Net.Http.Formatting/Formatting/MediaTypeWithQualityHeaderValueComparer.cs
@@ -36,13 +36,13 @@ public int Compare(MediaTypeWithQualityHeaderValue mediaType1, MediaTypeWithQual
Contract.Assert(mediaType1 != null, "The 'mediaType1' parameter should not be null.");
Contract.Assert(mediaType2 != null, "The 'mediaType2' parameter should not be null.");
- ParsedMediaTypeHeaderValue parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
- ParsedMediaTypeHeaderValue parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
-
- int returnValue = CompareBasedOnQualityFactor(parsedMediaType1, parsedMediaType2);
+ int returnValue = CompareBasedOnQualityFactor(mediaType1, mediaType2);
if (returnValue == 0)
{
+ ParsedMediaTypeHeaderValue parsedMediaType1 = new ParsedMediaTypeHeaderValue(mediaType1);
+ ParsedMediaTypeHeaderValue parsedMediaType2 = new ParsedMediaTypeHeaderValue(mediaType2);
+
if (!String.Equals(parsedMediaType1.Type, parsedMediaType2.Type, StringComparison.OrdinalIgnoreCase))
{
if (parsedMediaType1.IsAllMediaRange)
@@ -70,12 +70,12 @@ public int Compare(MediaTypeWithQualityHeaderValue mediaType1, MediaTypeWithQual
return returnValue;
}
- private static int CompareBasedOnQualityFactor(ParsedMediaTypeHeaderValue parsedMediaType1, ParsedMediaTypeHeaderValue parsedMediaType2)
+ private static int CompareBasedOnQualityFactor(MediaTypeWithQualityHeaderValue mediaType1, MediaTypeWithQualityHeaderValue mediaType2)
{
- Contract.Assert(parsedMediaType1 != null, "The 'parsedMediaType1' parameter should not be null.");
- Contract.Assert(parsedMediaType2 != null, "The 'parsedMediaType2' parameter should not be null.");
+ Contract.Assert(mediaType1 != null);
+ Contract.Assert(mediaType2 != null);
- double qualityDifference = parsedMediaType1.QualityFactor - parsedMediaType2.QualityFactor;
+ double? qualityDifference = mediaType1.Quality - mediaType2.Quality;
if (qualityDifference < 0)
{
return -1;
View
11 src/System.Net.Http.Formatting/Formatting/SecureJsonTextReader.cs
@@ -19,7 +19,7 @@ public override object Value
{
get
{
- if (this.ValueType == typeof(string))
+ if (ValueType == typeof(string))
{
return FixUpInvalidUnicodeString(base.Value as string);
}
@@ -29,11 +29,18 @@ public override object Value
public override bool Read()
{
+ int initialDepth = Depth;
+ bool didRead = base.Read();
if (Depth > _maxDepth)
{
+ // Advance the reader past the initial depth to avoid more exceptions from this violation
+ while (Depth > initialDepth)
+ {
+ base.Read();
+ }
throw new JsonReaderQuotaException(RS.Format(Properties.Resources.JsonTooDeep, _maxDepth));
}
- return base.Read();
+ return didRead;
}
private static string FixUpInvalidUnicodeString(string s)
View
2  src/System.Net.Http.Formatting/Formatting/XmlMediaTypeFormatter.cs
@@ -314,7 +314,7 @@ public override Task WriteToStreamAsync(Type type, object value, Stream stream,
isRemapped = MediaTypeFormatter.TryGetDelegatingTypeForIQueryableGenericOrSame(ref type);
}
- if (isRemapped)
+ if (isRemapped && value != null)
{
value = MediaTypeFormatter.GetTypeRemappingConstructor(type).Invoke(new object[] { value });
}
View
56 src/System.Net.Http.Formatting/FormattingUtilities.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Globalization;
using System.Linq;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
@@ -14,6 +15,32 @@ namespace System.Net.Http
/// </summary>
internal static class FormattingUtilities
{
+ // Supported date formats for input.
+ private static readonly string[] dateFormats = new string[]
+ {
+ // "r", // RFC 1123, required output format but too strict for input
+ "ddd, d MMM yyyy H:m:s 'GMT'", // RFC 1123 (r, except it allows both 1 and 01 for date and time)
+ "ddd, d MMM yyyy H:m:s", // RFC 1123, no zone - assume GMT
+ "d MMM yyyy H:m:s 'GMT'", // RFC 1123, no day-of-week
+ "d MMM yyyy H:m:s", // RFC 1123, no day-of-week, no zone
+ "ddd, d MMM yy H:m:s 'GMT'", // RFC 1123, short year
+ "ddd, d MMM yy H:m:s", // RFC 1123, short year, no zone
+ "d MMM yy H:m:s 'GMT'", // RFC 1123, no day-of-week, short year
+ "d MMM yy H:m:s", // RFC 1123, no day-of-week, short year, no zone
+
+ "dddd, d'-'MMM'-'yy H:m:s 'GMT'", // RFC 850
+ "dddd, d'-'MMM'-'yy H:m:s", // RFC 850 no zone
+ "ddd MMM d H:m:s yyyy", // ANSI C's asctime() format
+
+ "ddd, d MMM yyyy H:m:s zzz", // RFC 5322
+ "ddd, d MMM yyyy H:m:s", // RFC 5322 no zone
+ "d MMM yyyy H:m:s zzz", // RFC 5322 no day-of-week
+ "d MMM yyyy H:m:s", // RFC 5322 no day-of-week, no zone
+ };
+
+ // Valid header token characters are within the range 0x20 < c < 0x7F excluding the following characters
+ private const string NonTokenChars = "()<>@,;:\\\"/[]?={}";
+
/// <summary>
/// The default max depth for our formatter is 256
/// </summary>
@@ -182,5 +209,34 @@ public static string UnquoteToken(string token)
return token;
}
+
+ public static bool ValidateHeaderToken(string token)
+ {
+ return token != null && !token.Any(c => c < 0x21 || c > 0x7E || NonTokenChars.IndexOf(c) != -1);
+ }
+
+ public static string DateToString(DateTimeOffset dateTime)
+ {
+ // Format according to RFC1123; 'r' uses invariant info (DateTimeFormatInfo.InvariantInfo)
+ return dateTime.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture);
+ }
+
+ public static bool TryParseDate(string input, out DateTimeOffset result)
+ {
+ return DateTimeOffset.TryParseExact(input, dateFormats, DateTimeFormatInfo.InvariantInfo,
+ DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeUniversal,
+ out result);
+ }
+
+ /// <summary>
+ /// Parses valid integer strings with no leading signs, whitespace or other <see cref="NumberStyles"/>
+ /// </summary>
+ /// <param name="value">The value to parse</param>
+ /// <param name="result">The result</param>
+ /// <returns>True if value was valid; false otherwise.</returns>
+ public static bool TryParseInt32(string value, out int result)
+ {
+ return Int32.TryParse(value, NumberStyles.None, NumberFormatInfo.InvariantInfo, out result);
+ }
}
}
View
1  src/System.Net.Http.Formatting/GlobalSuppressions.cs
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "System.Net.Http.Headers")]
View
300 src/System.Net.Http.Formatting/Headers/CookieHeaderValue.cs
@@ -0,0 +1,300 @@
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Linq;
+using System.Net.Http.Formatting;
+using System.Text;
+using System.Web.Http;
+
+namespace System.Net.Http.Headers
+{
+ public class CookieHeaderValue : ICloneable
+ {
+ private const string ExpiresToken = "expires";
+ private const string MaxAgeToken = "max-age";
+ private const string DomainToken = "domain";
+ private const string PathToken = "path";
+ private const string SecureToken = "secure";
+ private const string HttpOnlyToken = "httponly";
+ private const string DefaultPath = "/";
+
+ private static readonly char[] segmentSeparator = new char[] { ';' };
+ private static readonly char[] nameValueSeparator = new char[] { '=' };
+
+ // Use list instead of dictionary since we may have multiple parameters with the same name.
+ private Collection<CookieState> _cookies;
+
+ public CookieHeaderValue(string name, string value)
+ {
+ CookieState cookie = new CookieState(name, value);
+ Cookies.Add(cookie);
+ }
+
+ public CookieHeaderValue(string name, NameValueCollection values)
+ {
+ CookieState cookie = new CookieState(name, values);
+ Cookies.Add(cookie);
+ }
+
+ /// <summary>
+ /// Constructor to be used by parser to create a new instance of this type.
+ /// </summary>
+ protected CookieHeaderValue()
+ {
+ }
+
+ private CookieHeaderValue(CookieHeaderValue source)
+ {
+ if (source == null)
+ {
+ throw Error.ArgumentNull("source");
+ }
+
+ Expires = source.Expires;
+ MaxAge = source.MaxAge;
+ Domain = source.Domain;
+ Path = source.Path;
+ Secure = source.Secure;
+ HttpOnly = source.HttpOnly;
+
+ foreach (CookieState cookie in source.Cookies)
+ {
+ Cookies.Add(cookie.Clone<CookieState>());
+ }
+ }
+
+ public Collection<CookieState> Cookies
+ {
+ get
+ {
+ if (_cookies == null)
+ {
+ _cookies = new Collection<CookieState>();
+ }
+ return _cookies;
+ }
+ }
+
+ public DateTimeOffset? Expires { get; set; }
+
+ public TimeSpan? MaxAge { get; set; }
+
+ public string Domain { get; set; }
+
+ public string Path { get; set; }
+
+ public bool Secure { get; set; }
+
+ public bool HttpOnly { get; set; }
+
+ public CookieState this[string name]
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(name))
+ {
+ return null;
+ }
+
+ CookieState cookie = Cookies.FirstOrDefault(c => String.Equals(c.Name, name, StringComparison.OrdinalIgnoreCase));
+ if (cookie == null)
+ {
+ cookie = new CookieState(name, String.Empty);
+ Cookies.Add(cookie);
+ }
+ return cookie;
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder header = new StringBuilder();
+ bool first = true;
+
+ foreach (CookieState cookie in Cookies)
+ {
+ first = AppendSegment(header, first, cookie.ToString(), null);
+ }
+
+ if (Expires.HasValue)
+ {
+ first = AppendSegment(header, first, ExpiresToken, FormattingUtilities.DateToString(Expires.Value));
+ }
+
+ if (MaxAge.HasValue)
+ {
+ first = AppendSegment(header, first, MaxAgeToken, ((int)MaxAge.Value.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo));
+ }
+
+ if (Domain != null)
+ {
+ first = AppendSegment(header, first, DomainToken, Domain);
+ }
+
+ if (Path != null)
+ {
+ first = AppendSegment(header, first, PathToken, Path);
+ }
+
+ if (Secure)
+ {
+ first = AppendSegment(header, first, SecureToken, null);
+ }
+
+ if (HttpOnly)
+ {
+ first = AppendSegment(header, first, HttpOnlyToken, null);
+ }
+
+ return header.ToString();
+ }
+
+ public object Clone()
+ {
+ return new CookieHeaderValue(this);
+ }
+
+ public static bool TryParse(string input, out CookieHeaderValue parsedValue)
+ {
+ parsedValue = null;
+ if (!String.IsNullOrEmpty(input))
+ {
+ string[] segments = input.Split(segmentSeparator);
+ CookieHeaderValue instance = new CookieHeaderValue();
+ foreach (string segment in segments)
+ {
+ if (!ParseCookieSegment(instance, segment))
+ {
+ return false;
+ }
+ }
+
+ // If we didn't find any cookie state name/value pairs then cookie is not valid
+ if (instance.Cookies.Count == 0)
+ {
+ return false;
+ }
+
+ parsedValue = instance;
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool AppendSegment(StringBuilder builder, bool first, string name, string value)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ builder.Append("; ");
+ }
+
+ builder.Append(name);
+ if (value != null)
+ {
+ builder.Append("=");
+ builder.Append(value);
+ }
+ return first;
+ }
+
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is a try method where we do want to ignore errors.")]
+ private static bool ParseCookieSegment(CookieHeaderValue instance, string segment)
+ {
+ if (String.IsNullOrWhiteSpace(segment))
+ {
+ return true;
+ }
+
+ string[] nameValue = segment.Split(nameValueSeparator, 2);
+ if (nameValue.Length < 1 || String.IsNullOrWhiteSpace(nameValue[0]))
+ {
+ return false;
+ }
+
+ string name = nameValue[0].Trim();
+ if (String.Equals(name, ExpiresToken, StringComparison.OrdinalIgnoreCase))
+ {
+ string value = GetSegmentValue(nameValue, null);
+ DateTimeOffset expires;
+ if (FormattingUtilities.TryParseDate(value, out expires))
+ {
+ instance.Expires = expires;
+ return true;
+ }
+ return false;
+ }
+ else if (String.Equals(name, MaxAgeToken, StringComparison.OrdinalIgnoreCase))
+ {
+ string value = GetSegmentValue(nameValue, null);
+ int maxAge;
+ if (FormattingUtilities.TryParseInt32(value, out maxAge))
+ {
+ instance.MaxAge = new TimeSpan(0, 0, maxAge);
+ return true;
+ }
+ return false;
+ }
+ else if (String.Equals(name, DomainToken, StringComparison.OrdinalIgnoreCase))
+ {
+ instance.Domain = GetSegmentValue(nameValue, null);
+ return true;
+ }
+ else if (String.Equals(name, PathToken, StringComparison.OrdinalIgnoreCase))
+ {
+ instance.Path = GetSegmentValue(nameValue, DefaultPath);
+ return true;
+ }
+ else if (String.Equals(name, SecureToken, StringComparison.OrdinalIgnoreCase))
+ {
+ string value = GetSegmentValue(nameValue, null);
+ if (!String.IsNullOrWhiteSpace(value))
+ {
+ return false;
+ }
+ instance.Secure = true;
+ return true;
+ }
+ else if (String.Equals(name, HttpOnlyToken, StringComparison.OrdinalIgnoreCase))
+ {
+ string value = GetSegmentValue(nameValue, null);
+ if (!String.IsNullOrWhiteSpace(value))
+ {
+ return false;
+ }
+ instance.HttpOnly = true;
+ return true;
+ }
+ else
+ {
+ string value = GetSegmentValue(nameValue, null);
+
+ // We read the cookie segment as form data
+ try
+ {
+ FormDataCollection formData = new FormDataCollection(value);
+ NameValueCollection values = formData.ReadAsNameValueCollection();
+ CookieState cookie = new CookieState(name, values);
+ instance.Cookies.Add(cookie);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ private static string GetSegmentValue(string[] nameValuePair, string defaultValue)
+ {
+ Contract.Assert(nameValuePair != null);
+ return nameValuePair.Length > 1 ? FormattingUtilities.UnquoteToken(nameValuePair[1]) : defaultValue;
+ }
+ }
+}
View
127 src/System.Net.Http.Formatting/Headers/CookieState.cs
@@ -0,0 +1,127 @@
+using System.Collections.Specialized;
+using System.Diagnostics.Contracts;
+using System.Net.Http.Formatting.Internal;
+using System.Web.Http;
+
+namespace System.Net.Http.Headers
+{
+ public class CookieState : ICloneable
+ {
+ private string _name;
+ private NameValueCollection _values = HttpValueCollection.Create();
+
+ public CookieState(string name)
+ : this(name, String.Empty)
+ {
+ }
+
+ public CookieState(string name, string value)
+ {
+ CheckNameFormat(name, "name");
+ _name = name;
+
+ CheckValueFormat(value, "value");
+ Value = value;
+ }
+
+ public CookieState(string name, NameValueCollection values)
+ {
+ CheckNameFormat(name, "name");
+ _name = name;
+
+ if (values == null)
+ {
+ throw Error.ArgumentNull("values");
+ }
+ Values.Add(values);
+ }
+
+ private CookieState(CookieState source)
+ {
+ Contract.Requires(source != null);
+
+ _name = source._name;
+ if (source._values != null)
+ {
+ Values.Add(source._values);
+ }
+ }
+
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ CheckNameFormat(value, "value");
+ _name = value;
+ }
+ }
+
+ /// <summary>
+ /// If the cookie data is a simple string value then set or retrieve it using the <see cref="Value"/> property.
+ /// If the cookie data is structured then use the <see cref="Values"/> property.
+ /// </summary>
+ public string Value
+ {
+ get
+ {
+ return Values.Count > 0 ? Values.AllKeys[0] : String.Empty;
+ }
+
+ set
+ {
+ CheckValueFormat(value, "value");
+ if (Values.Count > 0)
+ {
+ Values.AllKeys[0] = value;
+ }
+ else
+ {
+ Values.Add(value, String.Empty);
+ }
+ }
+ }
+
+ /// <summary>
+ /// If the cookie data is structured then use the <see cref="Values"/> property for setting and getting individual values.
+ /// If the cookie data is a simple string value then set or retrieve it using the <see cref="Value"/> property.
+ /// </summary>
+ public NameValueCollection Values
+ {
+ get { return _values; }
+ }
+
+ public string this[string name]
+ {
+ get { return Values[name]; }
+ set { Values[name] = value; }
+ }
+
+ public override string ToString()
+ {
+ return _name + "=" + (_values != null ? _values.ToString() : String.Empty);
+ }
+
+ public object Clone()
+ {
+ return new CookieState(this);
+ }
+
+ private static void CheckNameFormat(string name, string parameterName)
+ {
+ if (!FormattingUtilities.ValidateHeaderToken(name))
+ {
+ throw Error.Argument(parameterName, Properties.Resources.CookieInvalidName);
+ }
+ }
+
+ private static void CheckValueFormat(string value, string parameterName)
+ {
+ // Empty string is a valid cookie value
+ if (value == null)
+ {
+ throw Error.ArgumentNull(parameterName);
+ }
+ }
+ }
+}
View
6 src/System.Net.Http.Formatting/HttpContentExtensions.cs
@@ -113,10 +113,10 @@ private static Task<T> ReadAsAsync<T>(HttpContent content, Type type, IEnumerabl
throw new ArgumentNullException("formatters");
}
- ObjectContent obj = content as ObjectContent;
- if (obj != null)
+ ObjectContent objectContent = content as ObjectContent;
+ if (objectContent != null && objectContent.Value != null && type.IsAssignableFrom(objectContent.Value.GetType()))
{
- return TaskHelpers.FromResult((T)obj.Value);
+ return TaskHelpers.FromResult((T)objectContent.Value);
}
MediaTypeFormatter formatter = null;
View
58 src/System.Net.Http.Formatting/HttpRequestHeadersExtensions.cs
@@ -0,0 +1,58 @@