diff --git a/samples/webapi/AdvancedODataWebApiSample/AdvancedODataWebApiSample.csproj b/samples/webapi/AdvancedODataWebApiSample/AdvancedODataWebApiSample.csproj
index 7e644568..058d391e 100644
--- a/samples/webapi/AdvancedODataWebApiSample/AdvancedODataWebApiSample.csproj
+++ b/samples/webapi/AdvancedODataWebApiSample/AdvancedODataWebApiSample.csproj
@@ -48,13 +48,17 @@
True
-
- ..\..\..\packages\Microsoft.OData.Core.6.15.0\lib\portable-net45+win+wpa81\Microsoft.OData.Core.dll
- True
+
+ ..\..\..\packages\Microsoft.Extensions.DependencyInjection.1.0.0\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll
-
- ..\..\..\packages\Microsoft.OData.Edm.6.15.0\lib\portable-net45+win+wpa81\Microsoft.OData.Edm.dll
- True
+
+ ..\..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.0.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\..\..\packages\Microsoft.OData.Core.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Core.dll
+
+
+ ..\..\..\packages\Microsoft.OData.Edm.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll
..\..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
@@ -64,9 +68,8 @@
..\..\..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll
True
-
- ..\..\..\packages\Microsoft.Spatial.6.15.0\lib\portable-net45+win+wpa81\Microsoft.Spatial.dll
- True
+
+ ..\..\..\packages\Microsoft.Spatial.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.Spatial.dll
..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
@@ -98,9 +101,8 @@
..\..\..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
True
-
- ..\..\..\packages\Microsoft.AspNet.OData.5.9.1\lib\net45\System.Web.OData.dll
- True
+
+ ..\..\..\packages\Microsoft.AspNet.OData.6.0.0\lib\net45\System.Web.OData.dll
@@ -129,6 +131,7 @@
+
diff --git a/samples/webapi/AdvancedODataWebApiSample/CaseInsensitiveODataUriResolver.cs b/samples/webapi/AdvancedODataWebApiSample/CaseInsensitiveODataUriResolver.cs
new file mode 100644
index 00000000..113b81fa
--- /dev/null
+++ b/samples/webapi/AdvancedODataWebApiSample/CaseInsensitiveODataUriResolver.cs
@@ -0,0 +1,12 @@
+namespace Microsoft.Examples
+{
+ using Microsoft.OData.UriParser;
+ using System;
+
+ // HACK: required due to bug in ODL
+ // REF: https://github.com/OData/odata.net/issues/695
+ public sealed class CaseInsensitiveODataUriResolver : UnqualifiedODataUriResolver
+ {
+ public override bool EnableCaseInsensitive { get { return true; } set { } }
+ }
+}
\ No newline at end of file
diff --git a/samples/webapi/AdvancedODataWebApiSample/Startup.cs b/samples/webapi/AdvancedODataWebApiSample/Startup.cs
index ef3e728c..84ab63ac 100644
--- a/samples/webapi/AdvancedODataWebApiSample/Startup.cs
+++ b/samples/webapi/AdvancedODataWebApiSample/Startup.cs
@@ -4,12 +4,14 @@ namespace Microsoft.Examples
{
using Configuration;
using global::Owin;
+ using Microsoft.OData;
+ using Microsoft.OData.UriParser;
using Microsoft.Web.Http.Versioning;
using Microsoft.Web.OData.Builder;
using System.Web.Http;
using System.Web.OData.Batch;
using System.Web.OData.Builder;
- using System.Web.OData.Extensions;
+ using static Microsoft.OData.ServiceLifetime;
using static System.Web.Http.RouteParameter;
public class Startup
@@ -28,8 +30,6 @@ public void Configuration( IAppBuilder appBuilder )
new QueryStringApiVersionReader(),
new HeaderApiVersionReader( "api-version", "x-ms-version" ) );
} );
- configuration.EnableCaseInsensitive( true );
- configuration.EnableUnqualifiedNameCall( true );
var modelBuilder = new VersionedODataModelBuilder( configuration )
{
@@ -43,9 +43,14 @@ public void Configuration( IAppBuilder appBuilder )
var models = modelBuilder.GetEdmModels();
var batchHandler = new DefaultODataBatchHandler( httpServer );
- configuration.MapVersionedODataRoutes( "odata", "api", models, batchHandler );
+ configuration.MapVersionedODataRoutes( "odata", "api", models, ConfigureODataServices, batchHandler );
configuration.Routes.MapHttpRoute( "orders", "api/{controller}/{id}", new { id = Optional } );
appBuilder.UseWebApi( httpServer );
}
+
+ static void ConfigureODataServices( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton, typeof( ODataUriResolver ), sp => new CaseInsensitiveODataUriResolver() );
+ }
}
}
\ No newline at end of file
diff --git a/samples/webapi/AdvancedODataWebApiSample/packages.config b/samples/webapi/AdvancedODataWebApiSample/packages.config
index 2275831d..6b4617b1 100644
--- a/samples/webapi/AdvancedODataWebApiSample/packages.config
+++ b/samples/webapi/AdvancedODataWebApiSample/packages.config
@@ -1,16 +1,30 @@
-
+
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/webapi/BasicODataWebApiSample/BasicODataWebApiSample.csproj b/samples/webapi/BasicODataWebApiSample/BasicODataWebApiSample.csproj
index 675e6e3d..92f50292 100644
--- a/samples/webapi/BasicODataWebApiSample/BasicODataWebApiSample.csproj
+++ b/samples/webapi/BasicODataWebApiSample/BasicODataWebApiSample.csproj
@@ -51,13 +51,17 @@
True
-
- ..\..\..\packages\Microsoft.OData.Core.6.15.0\lib\portable-net45+win+wpa81\Microsoft.OData.Core.dll
- True
+
+ ..\..\..\packages\Microsoft.Extensions.DependencyInjection.1.0.0\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll
-
- ..\..\..\packages\Microsoft.OData.Edm.6.15.0\lib\portable-net45+win+wpa81\Microsoft.OData.Edm.dll
- True
+
+ ..\..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.0.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\..\..\packages\Microsoft.OData.Core.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Core.dll
+
+
+ ..\..\..\packages\Microsoft.OData.Edm.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll
..\..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
@@ -67,9 +71,8 @@
..\..\..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll
True
-
- ..\..\..\packages\Microsoft.Spatial.6.15.0\lib\portable-net45+win+wpa81\Microsoft.Spatial.dll
- True
+
+ ..\..\..\packages\Microsoft.Spatial.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.Spatial.dll
..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
@@ -101,9 +104,8 @@
..\..\..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
True
-
- ..\..\..\packages\Microsoft.AspNet.OData.5.9.1\lib\net45\System.Web.OData.dll
- True
+
+ ..\..\..\packages\Microsoft.AspNet.OData.6.0.0\lib\net45\System.Web.OData.dll
@@ -126,6 +128,7 @@
+
diff --git a/samples/webapi/BasicODataWebApiSample/CaseInsensitiveODataUriResolver.cs b/samples/webapi/BasicODataWebApiSample/CaseInsensitiveODataUriResolver.cs
new file mode 100644
index 00000000..113b81fa
--- /dev/null
+++ b/samples/webapi/BasicODataWebApiSample/CaseInsensitiveODataUriResolver.cs
@@ -0,0 +1,12 @@
+namespace Microsoft.Examples
+{
+ using Microsoft.OData.UriParser;
+ using System;
+
+ // HACK: required due to bug in ODL
+ // REF: https://github.com/OData/odata.net/issues/695
+ public sealed class CaseInsensitiveODataUriResolver : UnqualifiedODataUriResolver
+ {
+ public override bool EnableCaseInsensitive { get { return true; } set { } }
+ }
+}
\ No newline at end of file
diff --git a/samples/webapi/BasicODataWebApiSample/Startup.cs b/samples/webapi/BasicODataWebApiSample/Startup.cs
index 8aae1b74..77353fde 100644
--- a/samples/webapi/BasicODataWebApiSample/Startup.cs
+++ b/samples/webapi/BasicODataWebApiSample/Startup.cs
@@ -4,11 +4,13 @@ namespace Microsoft.Examples
{
using Configuration;
using global::Owin;
+ using Microsoft.OData;
+ using Microsoft.OData.UriParser;
using Microsoft.Web.OData.Builder;
using System.Web.Http;
using System.Web.OData.Batch;
using System.Web.OData.Builder;
- using System.Web.OData.Extensions;
+ using static Microsoft.OData.ServiceLifetime;
public class Startup
{
@@ -19,8 +21,6 @@ public void Configuration( IAppBuilder appBuilder )
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
configuration.AddApiVersioning( o => o.ReportApiVersions = true );
- configuration.EnableCaseInsensitive( true );
- configuration.EnableUnqualifiedNameCall( true );
var modelBuilder = new VersionedODataModelBuilder( configuration )
{
@@ -34,9 +34,14 @@ public void Configuration( IAppBuilder appBuilder )
var models = modelBuilder.GetEdmModels();
var batchHandler = new DefaultODataBatchHandler( httpServer );
- configuration.MapVersionedODataRoutes( "odata", "api", models, batchHandler );
- configuration.MapVersionedODataRoutes( "odata-bypath", "v{apiVersion}", models, batchHandler );
+ configuration.MapVersionedODataRoutes( "odata", "api", models, ConfigureODataServices, batchHandler );
+ configuration.MapVersionedODataRoutes( "odata-bypath", "v{apiVersion}", models, ConfigureODataServices );
appBuilder.UseWebApi( httpServer );
}
+
+ static void ConfigureODataServices( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton, typeof( ODataUriResolver ), sp => new CaseInsensitiveODataUriResolver() );
+ }
}
}
\ No newline at end of file
diff --git a/samples/webapi/BasicODataWebApiSample/packages.config b/samples/webapi/BasicODataWebApiSample/packages.config
index 2275831d..6b4617b1 100644
--- a/samples/webapi/BasicODataWebApiSample/packages.config
+++ b/samples/webapi/BasicODataWebApiSample/packages.config
@@ -1,16 +1,30 @@
-
+
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/webapi/ConventionsODataWebApiSample/CaseInsensitiveODataUriResolver.cs b/samples/webapi/ConventionsODataWebApiSample/CaseInsensitiveODataUriResolver.cs
new file mode 100644
index 00000000..113b81fa
--- /dev/null
+++ b/samples/webapi/ConventionsODataWebApiSample/CaseInsensitiveODataUriResolver.cs
@@ -0,0 +1,12 @@
+namespace Microsoft.Examples
+{
+ using Microsoft.OData.UriParser;
+ using System;
+
+ // HACK: required due to bug in ODL
+ // REF: https://github.com/OData/odata.net/issues/695
+ public sealed class CaseInsensitiveODataUriResolver : UnqualifiedODataUriResolver
+ {
+ public override bool EnableCaseInsensitive { get { return true; } set { } }
+ }
+}
\ No newline at end of file
diff --git a/samples/webapi/ConventionsODataWebApiSample/ConventionsODataWebApiSample.csproj b/samples/webapi/ConventionsODataWebApiSample/ConventionsODataWebApiSample.csproj
index dce94d47..634f1d12 100644
--- a/samples/webapi/ConventionsODataWebApiSample/ConventionsODataWebApiSample.csproj
+++ b/samples/webapi/ConventionsODataWebApiSample/ConventionsODataWebApiSample.csproj
@@ -48,13 +48,17 @@
True
-
- ..\..\..\packages\Microsoft.OData.Core.6.15.0\lib\portable-net45+win+wpa81\Microsoft.OData.Core.dll
- True
+
+ ..\..\..\packages\Microsoft.Extensions.DependencyInjection.1.0.0\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll
-
- ..\..\..\packages\Microsoft.OData.Edm.6.15.0\lib\portable-net45+win+wpa81\Microsoft.OData.Edm.dll
- True
+
+ ..\..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.0.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\..\..\packages\Microsoft.OData.Core.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Core.dll
+
+
+ ..\..\..\packages\Microsoft.OData.Edm.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll
..\..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll
@@ -64,9 +68,8 @@
..\..\..\packages\Microsoft.Owin.Host.SystemWeb.3.0.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll
True
-
- ..\..\..\packages\Microsoft.Spatial.6.15.0\lib\portable-net45+win+wpa81\Microsoft.Spatial.dll
- True
+
+ ..\..\..\packages\Microsoft.Spatial.7.0.0\lib\portable-net45+win8+wpa81\Microsoft.Spatial.dll
..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll
@@ -98,9 +101,8 @@
..\..\..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
True
-
- ..\..\..\packages\Microsoft.AspNet.OData.5.9.1\lib\net45\System.Web.OData.dll
- True
+
+ ..\..\..\packages\Microsoft.AspNet.OData.6.0.0\lib\net45\System.Web.OData.dll
@@ -123,6 +125,7 @@
+
diff --git a/samples/webapi/ConventionsODataWebApiSample/Startup.cs b/samples/webapi/ConventionsODataWebApiSample/Startup.cs
index c0742bfc..bdd44d48 100644
--- a/samples/webapi/ConventionsODataWebApiSample/Startup.cs
+++ b/samples/webapi/ConventionsODataWebApiSample/Startup.cs
@@ -5,12 +5,14 @@ namespace Microsoft.Examples
using Configuration;
using Controllers;
using global::Owin;
+ using Microsoft.OData;
+ using Microsoft.OData.UriParser;
using Microsoft.Web.Http.Versioning.Conventions;
using Microsoft.Web.OData.Builder;
using System.Web.Http;
using System.Web.OData.Batch;
using System.Web.OData.Builder;
- using System.Web.OData.Extensions;
+ using static Microsoft.OData.ServiceLifetime;
public class Startup
{
@@ -37,8 +39,6 @@ public void Configuration( IAppBuilder appBuilder )
options.Conventions.Controller()
.HasApiVersion( 3, 0 );
} );
- configuration.EnableCaseInsensitive( true );
- configuration.EnableUnqualifiedNameCall( true );
var modelBuilder = new VersionedODataModelBuilder( configuration )
{
@@ -52,9 +52,14 @@ public void Configuration( IAppBuilder appBuilder )
var models = modelBuilder.GetEdmModels();
var batchHandler = new DefaultODataBatchHandler( httpServer );
- configuration.MapVersionedODataRoutes( "odata", "api", models, batchHandler );
- configuration.MapVersionedODataRoutes( "odata-bypath", "v{apiVersion}", models, batchHandler );
+ configuration.MapVersionedODataRoutes( "odata", "api", models, ConfigureODataServices, batchHandler );
+ configuration.MapVersionedODataRoutes( "odata-bypath", "v{apiVersion}", models, ConfigureODataServices );
appBuilder.UseWebApi( httpServer );
}
+
+ static void ConfigureODataServices( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton, typeof( ODataUriResolver ), sp => new CaseInsensitiveODataUriResolver() );
+ }
}
}
\ No newline at end of file
diff --git a/samples/webapi/ConventionsODataWebApiSample/packages.config b/samples/webapi/ConventionsODataWebApiSample/packages.config
index 2275831d..6b4617b1 100644
--- a/samples/webapi/ConventionsODataWebApiSample/packages.config
+++ b/samples/webapi/ConventionsODataWebApiSample/packages.config
@@ -1,16 +1,30 @@
-
+
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.OData.Versioning/Microsoft.AspNet.OData.Versioning.csproj b/src/Microsoft.AspNet.OData.Versioning/Microsoft.AspNet.OData.Versioning.csproj
index 91cfc19d..5548d60f 100644
--- a/src/Microsoft.AspNet.OData.Versioning/Microsoft.AspNet.OData.Versioning.csproj
+++ b/src/Microsoft.AspNet.OData.Versioning/Microsoft.AspNet.OData.Versioning.csproj
@@ -17,7 +17,7 @@
-
+
@@ -25,6 +25,21 @@
+
+
+ SR.resx
+ True
+ True
+
+
+
+
+
+ SR.Designer.cs
+ ResXFileCodeGenerator
+
+
+
diff --git a/src/Microsoft.AspNet.OData.Versioning/SR.Designer.cs b/src/Microsoft.AspNet.OData.Versioning/SR.Designer.cs
new file mode 100644
index 00000000..e9ce6a22
--- /dev/null
+++ b/src/Microsoft.AspNet.OData.Versioning/SR.Designer.cs
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class SR {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal SR() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SR", typeof(SR).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The container built by the container builder must not be null..
+ ///
+ internal static string NullContainer {
+ get {
+ return ResourceManager.GetString("NullContainer", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The container builder created by the container builder factory must not be null..
+ ///
+ internal static string NullContainerBuilder {
+ get {
+ return ResourceManager.GetString("NullContainerBuilder", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.OData.Versioning/SR.resx b/src/Microsoft.AspNet.OData.Versioning/SR.resx
new file mode 100644
index 00000000..db2fc33b
--- /dev/null
+++ b/src/Microsoft.AspNet.OData.Versioning/SR.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ The container built by the container builder must not be null.
+
+
+ The container builder created by the container builder factory must not be null.
+
+
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/HttpConfigurationExtensions.cs b/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/HttpConfigurationExtensions.cs
index 81840004..9df1f684 100644
--- a/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/HttpConfigurationExtensions.cs
+++ b/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/HttpConfigurationExtensions.cs
@@ -6,6 +6,8 @@
using Diagnostics.Contracts;
using Linq;
using Microsoft;
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.OData;
using Microsoft.OData.Edm;
using Microsoft.Web.Http;
using Microsoft.Web.Http.Routing;
@@ -16,7 +18,10 @@
using OData.Routing;
using OData.Routing.Conventions;
using Routing;
- using static Linq.Expressions.Expression;
+ using System.Collections.Concurrent;
+ using System.Net.Http;
+ using System.Web.OData;
+ using static Microsoft.OData.ServiceLifetime;
using static System.String;
using static System.StringComparison;
@@ -25,86 +30,132 @@
///
public static class HttpConfigurationExtensions
{
- const string ResolverSettingsKey = "System.Web.OData.ResolverSettingsKey";
+ const string ContainerBuilderFactoryKey = "System.Web.OData.ContainerBuilderFactoryKey";
+ const string RootContainerMappingsKey = "System.Web.OData.RootContainerMappingsKey";
+ const string UrlKeyDelimiterKey = "System.Web.OData.UrlKeyDelimiterKey";
const string UnversionedRouteSuffix = "-Unversioned";
const string ApiVersionConstraintName = "apiVersion";
const string ApiVersionConstraint = "{" + ApiVersionConstraintName + "}";
- static readonly Lazy> setResolverSettings = new Lazy>( GetResolverSettingsMutator );
- static Action GetResolverSettingsMutator()
- {
- Contract.Ensures( Contract.Result>() != null );
-
- // build a strong-typed delegate to the DefaultODataPathHandler.ResolverSettings property mutator
- var handlerType = typeof( DefaultODataPathHandler );
- var resolverSettingsType = handlerType.Assembly.GetType( "System.Web.OData.ODataUriResolverSetttings" );
- var h = Parameter( handlerType, "h" );
- var rs = Parameter( typeof( object ), "rs" );
- var property = Property( h, "ResolverSetttings" );
- var body = Assign( property, Convert( rs, resolverSettingsType ) );
- var lambda = Lambda>( body, h, rs );
- var action = lambda.Compile();
-
- return action;
- }
+ ///
+ /// Maps the specified versioned OData routes.
+ ///
+ /// The extended HTTP configuration.
+ /// The name of the route to map.
+ /// The prefix to add to the OData route's path template.
+ /// The sequence of EDM models to use for parsing OData paths.
+ /// The configuring action to add the services to the root container.
+ /// The read-only list of added OData routes.
+ /// The specified must contain the API version annotation. This annotation is
+ /// automatically applied when you use the and call to
+ /// create the .
+ public static IReadOnlyList MapVersionedODataRoutes(
+ this HttpConfiguration configuration,
+ string routeName,
+ string routePrefix,
+ IEnumerable models,
+ Action configureAction ) =>
+ MapVersionedODataRoutes( configuration, routeName, routePrefix, models, configureAction, null );
- static void SetResolverSettings( this HttpConfiguration configuration, IODataPathHandler pathHandler )
+ ///
+ /// Maps the specified versioned OData routes.
+ ///
+ /// The extended HTTP configuration.
+ /// The name of the route to map.
+ /// The prefix to add to the OData route's path template.
+ /// The sequence of EDM models to use for parsing OData paths.
+ /// The configuring action to add the services to the root container.
+ /// The OData batch handler.
+ /// The read-only list of added OData routes.
+ /// The specified must contain the API version annotation. This annotation is
+ /// automatically applied when you use the and call to
+ /// create the .
+ public static IReadOnlyList MapVersionedODataRoutes(
+ this HttpConfiguration configuration,
+ string routeName,
+ string routePrefix,
+ IEnumerable models,
+ Action configureAction,
+ ODataBatchHandler batchHandler )
{
- Contract.Requires( configuration != null );
+ Arg.NotNull( configuration, nameof( configuration ) );
+ Arg.NotNull( models, nameof( models ) );
+ Contract.Ensures( Contract.Result>() != null );
- // REMARKS: the DefaultODataPathHandler.ResolverSettings property is internal as is the ODataUriResolverSetttings class.
- // The MapODataServiceRoute normally hooks this up, but we are replacing that process. in order to retain functional
- // fidelity we'll build and compile a strong-typed delegate that can be used to set the property.
- //
- // in additional, the ODataUriResolverSetttings are created lazy-initialized from the property bag. instead of using
- // Reflection, we'll test for the known key. if the key is not present, we'll use a public extension method
- // (e.g. EnableCaseInsensitive) with the default, unconfigured value. this will trigger the creation of the
- // settings and populate the property.
+ object ConfigureRoutingConventions( IEdmModel model, string versionedRouteName, ApiVersion apiVersion )
+ {
+ var routingConventions = EnsureConventions( ODataRoutingConventions.CreateDefault() );
- var handler = pathHandler as DefaultODataPathHandler;
+ model.SetAnnotationValue( model, new ApiVersionAnnotation( apiVersion ) );
+ routingConventions.Insert( 0, new VersionedAttributeRoutingConvention( versionedRouteName, configuration, apiVersion ) );
- if ( handler == null )
- {
- return;
+ return routingConventions.ToArray();
}
- // REMARKS: this creates and populates the ODataUriResolverSetttings; OData URLs are case-sensitive by default.
- if ( !configuration.Properties.ContainsKey( ResolverSettingsKey ) )
+ if ( !IsNullOrEmpty( routePrefix ) )
{
- configuration.EnableCaseInsensitive( false );
+ routePrefix = routePrefix.TrimEnd( '/' );
}
- setResolverSettings.Value( handler, configuration.Properties[ResolverSettingsKey] );
- }
+ var routes = configuration.Routes;
+ var unversionedRouteName = routeName + UnversionedRouteSuffix;
- static IList EnsureConventions( IList conventions )
- {
- Contract.Requires( conventions != null );
- Contract.Ensures( Contract.Result>() != null );
+ if ( batchHandler != null )
+ {
+ batchHandler.ODataRouteName = unversionedRouteName;
+ var batchTemplate = IsNullOrEmpty( routePrefix ) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
+ routes.MapHttpBatchRoute( routeName + nameof( ODataRouteConstants.Batch ), batchTemplate, batchHandler );
+ }
- var discovered = new BitVector32( 0 );
+ var odataRoutes = new List();
+ var unversionedConstraints = new List();
- for ( var i = 0; i < conventions.Count; i++ )
+ foreach ( var model in models )
{
- var convention = conventions[i];
+ var versionedRouteName = routeName;
+ var apiVersion = model.GetAnnotationValue( model )?.ApiVersion;
+ var routeConstraint = MakeVersionedODataRouteConstraint( apiVersion, ref versionedRouteName );
- if ( convention is MetadataRoutingConvention )
+ unversionedConstraints.Add( new ODataPathRouteConstraint( versionedRouteName ) );
+
+ var rootContainer = configuration.CreateODataRootContainer(
+ versionedRouteName,
+ builder =>
+ {
+ builder.AddService( Singleton, typeof( IEdmModel ), sp => model )
+ .AddService( Singleton, typeof( IEnumerable ), sp => ConfigureRoutingConventions( model, versionedRouteName, apiVersion ) );
+ configureAction?.Invoke( builder );
+ } );
+
+ var pathHandler = rootContainer.GetRequiredService();
+
+ if ( pathHandler != null && pathHandler.UrlKeyDelimiter == null )
{
- conventions[i] = new VersionedMetadataRoutingConvention();
- discovered[1] = true;
+ pathHandler.UrlKeyDelimiter = configuration.GetUrlKeyDelimiter();
}
- else if ( convention is VersionedMetadataRoutingConvention )
+
+ rootContainer.InitializeAttributeRouting();
+
+ var route = default( ODataRoute );
+ var messageHandler = rootContainer.GetService();
+
+ if ( messageHandler == null )
{
- discovered[1] = true;
+ route = new ODataRoute( routePrefix, routeConstraint );
+ }
+ else
+ {
+ route = new ODataRoute( routePrefix, routeConstraint, defaults: null, constraints: null, dataTokens: null, handler: messageHandler );
}
- }
- if ( !discovered[1] )
- {
- conventions.Insert( 0, new VersionedMetadataRoutingConvention() );
+ routes.Add( versionedRouteName, route );
+ AddApiVersionConstraintIfNecessary( route );
+ odataRoutes.Add( route );
}
- return conventions;
+ configuration.AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch( unversionedRouteName, routePrefix, odataRoutes, unversionedConstraints, configureAction );
+
+ return odataRoutes;
}
///
@@ -119,7 +170,7 @@ static IList EnsureConventions( IList and call to
/// create the .
public static IReadOnlyList MapVersionedODataRoutes( this HttpConfiguration configuration, string routeName, string routePrefix, IEnumerable models ) =>
- MapVersionedODataRoutes( configuration, routeName, routePrefix, models, null );
+ MapVersionedODataRoutes( configuration, routeName, routePrefix, models, new DefaultODataPathHandler(), ODataRoutingConventions.CreateDefault(), null );
///
/// Maps the specified versioned OData routes. When the is provided, it will create a
@@ -198,6 +249,7 @@ public static IReadOnlyList MapVersionedODataRoutes(
var routeConventions = EnsureConventions( routingConventions.ToList() );
var routes = configuration.Routes;
+ var unversionedRouteName = routeName + UnversionedRouteSuffix;
if ( !IsNullOrEmpty( routePrefix ) )
{
@@ -206,11 +258,16 @@ public static IReadOnlyList MapVersionedODataRoutes(
if ( batchHandler != null )
{
+ batchHandler.ODataRouteName = unversionedRouteName;
var batchTemplate = IsNullOrEmpty( routePrefix ) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
- routes.MapHttpBatchRoute( routeName + "Batch", batchTemplate, batchHandler );
+ routes.MapHttpBatchRoute( routeName + nameof( ODataRouteConstants.Batch ), batchTemplate, batchHandler );
+ }
+
+ if ( pathHandler != null && pathHandler.UrlKeyDelimiter == null )
+ {
+ pathHandler.UrlKeyDelimiter = configuration.GetUrlKeyDelimiter();
}
- configuration.SetResolverSettings( pathHandler );
routeConventions.Insert( 0, null );
var odataRoutes = new List();
@@ -219,25 +276,132 @@ public static IReadOnlyList MapVersionedODataRoutes(
foreach ( var model in models )
{
var versionedRouteName = routeName;
- var routeConstraint = default( ODataPathRouteConstraint );
+ var apiVersion = model.GetAnnotationValue( model )?.ApiVersion;
+ var routeConstraint = MakeVersionedODataRouteConstraint( apiVersion, ref versionedRouteName );
- routeConventions[0] = new VersionedAttributeRoutingConvention( model, configuration );
- routeConstraint = new ODataPathRouteConstraint( pathHandler, model, versionedRouteName, routeConventions.ToArray() );
- unversionedConstraints.Add( routeConstraint );
- routeConstraint = MakeVersionedODataRouteConstraint( routeConstraint, pathHandler, routeConventions, model, ref versionedRouteName );
+ routeConventions[0] = new VersionedAttributeRoutingConvention( versionedRouteName, configuration, apiVersion );
+ unversionedConstraints.Add( new ODataPathRouteConstraint( versionedRouteName ) );
- var route = new ODataRoute( routePrefix, routeConstraint );
+ var rootContainer = configuration.CreateODataRootContainer(
+ versionedRouteName,
+ builder => builder.AddService( Singleton, typeof( IEdmModel ), sp => model )
+ .AddService( Singleton, typeof( IODataPathHandler ), sp => pathHandler )
+ .AddService( Singleton, typeof( IEnumerable ), sp => routeConventions.ToArray() )
+ .AddService( Singleton, typeof( ODataBatchHandler ), sp => batchHandler ) );
+
+ rootContainer.InitializeAttributeRouting();
+
+ var route = default( ODataRoute );
+ var messageHandler = rootContainer.GetService();
+
+
+ if ( messageHandler == null )
+ {
+ route = new ODataRoute( routePrefix, routeConstraint );
+ }
+ else
+ {
+ route = new ODataRoute( routePrefix, routeConstraint, defaults: null, constraints: null, dataTokens: null, handler: messageHandler );
+ }
- AddApiVersionConstraintIfNecessary( route );
routes.Add( versionedRouteName, route );
+ AddApiVersionConstraintIfNecessary( route );
odataRoutes.Add( route );
}
- AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch( routeName, routePrefix, routes, odataRoutes, unversionedConstraints );
+ configuration.AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch( unversionedRouteName, routePrefix, odataRoutes, unversionedConstraints, _ => { } );
return odataRoutes;
}
+ ///
+ /// Maps the specified OData route and the OData route attributes.
+ ///
+ /// The server configuration.
+ /// The name of the route to map.
+ /// The prefix to add to the OData route's path template.
+ /// The API version associated with the model.
+ /// The configuring action to add the services to the root container.
+ /// The added .
+ public static ODataRoute MapVersionedODataRoute( this HttpConfiguration configuration, string routeName, string routePrefix, ApiVersion apiVersion, Action configureAction )
+ {
+ Arg.NotNull( configuration, nameof( configuration ) );
+ Arg.NotNull( apiVersion, nameof( apiVersion ) );
+ Contract.Ensures( Contract.Result() != null );
+
+ object ConfigureRoutingConventions( IServiceProvider serviceProvider )
+ {
+ var model = serviceProvider.GetRequiredService();
+ var routingConventions = EnsureConventions( ODataRoutingConventions.CreateDefault() );
+
+ model.SetAnnotationValue( model, new ApiVersionAnnotation( apiVersion ) );
+ routingConventions.Insert( 0, new VersionedAttributeRoutingConvention( routeName, configuration, apiVersion ) );
+
+ return routingConventions.ToArray();
+ }
+
+ if ( !IsNullOrEmpty( routePrefix ) )
+ {
+ routePrefix = routePrefix.TrimEnd( '/' );
+ }
+
+ var rootContainer = configuration.CreateODataRootContainer(
+ routeName,
+ builder =>
+ {
+ builder.AddService( Singleton, typeof( IEnumerable ), ConfigureRoutingConventions );
+ configureAction?.Invoke( builder );
+ } );
+ var pathHandler = rootContainer.GetRequiredService();
+
+ if ( pathHandler != null && pathHandler.UrlKeyDelimiter == null )
+ {
+ pathHandler.UrlKeyDelimiter = configuration.GetUrlKeyDelimiter();
+ }
+
+ rootContainer.InitializeAttributeRouting();
+
+ var routeConstraint = new VersionedODataPathRouteConstraint( routeName, apiVersion );
+ var route = default( ODataRoute );
+ var routes = configuration.Routes;
+ var messageHandler = rootContainer.GetService();
+
+ if ( messageHandler != null )
+ {
+ route = new ODataRoute(
+ routePrefix,
+ routeConstraint,
+ defaults: null,
+ constraints: null,
+ dataTokens: null,
+ handler: messageHandler );
+ }
+ else
+ {
+ var batchHandler = rootContainer.GetService();
+
+ if ( batchHandler != null )
+ {
+ batchHandler.ODataRouteName = routeName;
+ var batchTemplate = IsNullOrEmpty( routePrefix ) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
+ routes.MapHttpBatchRoute( routeName + nameof( ODataRouteConstants.Batch ), batchTemplate, batchHandler );
+ }
+
+ route = new ODataRoute( routePrefix, routeConstraint );
+ }
+
+ routes.Add( routeName, route );
+ AddApiVersionConstraintIfNecessary( route );
+
+ var unversionedRouteConstraint = new ODataPathRouteConstraint( routeName );
+ var unversionedRoute = new ODataRoute( routePrefix, new UnversionedODataPathRouteConstraint( unversionedRouteConstraint, apiVersion ) );
+
+ AddApiVersionConstraintIfNecessary( unversionedRoute );
+ configuration.Routes.Add( routeName + UnversionedRouteSuffix, unversionedRoute );
+
+ return route;
+ }
+
///
/// Maps a versioned OData route.
///
@@ -250,7 +414,7 @@ public static IReadOnlyList MapVersionedODataRoutes(
/// The API version annotation will be added or updated on the specified using
/// the provided API version.
public static ODataRoute MapVersionedODataRoute( this HttpConfiguration configuration, string routeName, string routePrefix, IEdmModel model, ApiVersion apiVersion ) =>
- MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, new DefaultODataPathHandler(), ODataRoutingConventions.CreateDefault(), null );
+ MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, new DefaultODataPathHandler(), ODataRoutingConventions.CreateDefault(), null, null );
///
/// Maps a versioned OData route.
@@ -271,7 +435,27 @@ public static ODataRoute MapVersionedODataRoute(
IEdmModel model,
ApiVersion apiVersion,
ODataBatchHandler batchHandler ) =>
- MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, new DefaultODataPathHandler(), ODataRoutingConventions.CreateDefault(), batchHandler );
+ MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, new DefaultODataPathHandler(), ODataRoutingConventions.CreateDefault(), batchHandler, null );
+
+ ///
+ /// Maps the specified OData route and the OData route attributes. When the
+ /// is non-null, it will map it as the default handler for the route.
+ ///
+ /// The server configuration.
+ /// The name of the route to map.
+ /// The prefix to add to the OData route's path template.
+ /// The EDM model to use for parsing OData paths.
+ /// The API version associated with the model.
+ /// The default for this route.
+ /// The added .
+ public static ODataRoute MapVersionedODataRoute(
+ this HttpConfiguration configuration,
+ string routeName,
+ string routePrefix,
+ IEdmModel model,
+ ApiVersion apiVersion,
+ HttpMessageHandler defaultHandler ) =>
+ MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, new DefaultODataPathHandler(), ODataRoutingConventions.CreateDefault(), null, defaultHandler );
///
/// Maps a versioned OData route.
@@ -295,7 +479,7 @@ public static ODataRoute MapVersionedODataRoute(
ApiVersion apiVersion,
IODataPathHandler pathHandler,
IEnumerable routingConventions ) =>
- MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, pathHandler, routingConventions, null );
+ MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, pathHandler, routingConventions, null, null );
///
/// Maps a versioned OData route. When the is provided, it will create a '$batch' endpoint to handle the batch requests.
@@ -322,7 +506,45 @@ public static ODataRoute MapVersionedODataRoute(
ApiVersion apiVersion,
IODataPathHandler pathHandler,
IEnumerable routingConventions,
- ODataBatchHandler batchHandler )
+ ODataBatchHandler batchHandler ) =>
+ MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, pathHandler, routingConventions, batchHandler, null );
+
+ ///
+ /// Maps the specified OData route. When the is non-null, it will map
+ /// it as the handler for the route.
+ ///
+ /// The server configuration.
+ /// The name of the route to map.
+ /// The prefix to add to the OData route's path template.
+ /// The EDM model to use for parsing OData paths.
+ /// The API version associated with the model.
+ /// The to use for parsing the OData path.
+ /// The OData routing conventions to use for controller and action selection.
+ /// The default for this route.
+ /// The added .
+ public static ODataRoute MapVersionedODataRoute(
+ this HttpConfiguration configuration,
+ string routeName,
+ string routePrefix,
+ IEdmModel model,
+ ApiVersion apiVersion,
+ IODataPathHandler pathHandler,
+ IEnumerable routingConventions,
+ HttpMessageHandler defaultHandler ) =>
+ MapVersionedODataRoute( configuration, routeName, routePrefix, model, apiVersion, pathHandler, routingConventions, null, defaultHandler );
+
+ [SuppressMessage( "Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Validated by a code contract." )]
+ [SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "The specified handler must be the batch handler." )]
+ static ODataRoute MapVersionedODataRoute(
+ HttpConfiguration configuration,
+ string routeName,
+ string routePrefix,
+ IEdmModel model,
+ ApiVersion apiVersion,
+ IODataPathHandler pathHandler,
+ IEnumerable routingConventions,
+ ODataBatchHandler batchHandler,
+ HttpMessageHandler defaultHandler )
{
Arg.NotNull( configuration, nameof( configuration ) );
Arg.NotNull( model, nameof( model ) );
@@ -337,23 +559,47 @@ public static ODataRoute MapVersionedODataRoute(
routePrefix = routePrefix.TrimEnd( '/' );
}
- if ( batchHandler != null )
+ if ( pathHandler != null && pathHandler.UrlKeyDelimiter == null )
{
- var batchTemplate = IsNullOrEmpty( routePrefix ) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
- routes.MapHttpBatchRoute( routeName + "Batch", batchTemplate, batchHandler );
+ pathHandler.UrlKeyDelimiter = configuration.GetUrlKeyDelimiter();
}
- configuration.SetResolverSettings( pathHandler );
model.SetAnnotationValue( model, new ApiVersionAnnotation( apiVersion ) );
- routeConventions.Insert( 0, new VersionedAttributeRoutingConvention( model, configuration ) );
+ routeConventions.Insert( 0, new VersionedAttributeRoutingConvention( routeName, configuration, apiVersion ) );
- var routeConstraint = new VersionedODataPathRouteConstraint( pathHandler, model, routeName, routeConventions.ToArray(), apiVersion );
- var route = new ODataRoute( routePrefix, routeConstraint );
+ var rootContainer = configuration.CreateODataRootContainer(
+ routeName,
+ builder => builder.AddService( Singleton, typeof( IEdmModel ), sp => model )
+ .AddService( Singleton, typeof( IODataPathHandler ), sp => pathHandler )
+ .AddService( Singleton, typeof( IEnumerable ), sp => routeConventions.ToArray() )
+ .AddService( Singleton, typeof( ODataBatchHandler ), sp => batchHandler )
+ .AddService( Singleton, typeof( HttpMessageHandler ), sp => defaultHandler ) );
+
+ rootContainer.InitializeAttributeRouting();
+
+ var routeConstraint = new VersionedODataPathRouteConstraint( routeName, apiVersion );
+ var route = default( ODataRoute );
+
+ if ( defaultHandler != null )
+ {
+ route = new ODataRoute( routePrefix, routeConstraint, defaults: null, constraints: null, dataTokens: null, handler: defaultHandler );
+ }
+ else
+ {
+ if ( batchHandler != null )
+ {
+ batchHandler.ODataRouteName = routeName;
+ var batchTemplate = IsNullOrEmpty( routePrefix ) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
+ routes.MapHttpBatchRoute( routeName + nameof( ODataRouteConstants.Batch ), batchTemplate, batchHandler );
+ }
+
+ route = new ODataRoute( routePrefix, routeConstraint );
+ }
- AddApiVersionConstraintIfNecessary( route );
routes.Add( routeName, route );
+ AddApiVersionConstraintIfNecessary( route );
- var unversionedRouteConstraint = new ODataPathRouteConstraint( pathHandler, model, routeName, routeConventions.ToArray() );
+ var unversionedRouteConstraint = new ODataPathRouteConstraint( routeName );
var unversionedRoute = new ODataRoute( routePrefix, new UnversionedODataPathRouteConstraint( unversionedRouteConstraint, apiVersion ) );
AddApiVersionConstraintIfNecessary( unversionedRoute );
@@ -362,29 +608,48 @@ public static ODataRoute MapVersionedODataRoute(
return route;
}
- static ODataPathRouteConstraint MakeVersionedODataRouteConstraint(
- ODataPathRouteConstraint routeConstraint,
- IODataPathHandler pathHandler,
- IList routeConventions,
- IEdmModel model,
- ref string versionedRouteName )
+ static IList EnsureConventions( IList conventions )
+ {
+ Contract.Requires( conventions != null );
+ Contract.Ensures( Contract.Result>() != null );
+
+ var discovered = new BitVector32( 0 );
+
+ for ( var i = 0; i < conventions.Count; i++ )
+ {
+ var convention = conventions[i];
+
+ if ( convention is MetadataRoutingConvention )
+ {
+ conventions[i] = new VersionedMetadataRoutingConvention();
+ discovered[1] = true;
+ }
+ else if ( convention is VersionedMetadataRoutingConvention )
+ {
+ discovered[1] = true;
+ }
+ }
+
+ if ( !discovered[1] )
+ {
+ conventions.Insert( 0, new VersionedMetadataRoutingConvention() );
+ }
+
+ return conventions;
+ }
+
+ static ODataPathRouteConstraint MakeVersionedODataRouteConstraint( ApiVersion apiVersion, ref string versionedRouteName )
{
- Contract.Requires( routeConstraint != null );
- Contract.Requires( pathHandler != null );
- Contract.Requires( routeConventions != null );
- Contract.Requires( model != null );
Contract.Requires( !IsNullOrEmpty( versionedRouteName ) );
Contract.Ensures( Contract.Result() != null );
- var apiVersion = model.GetAnnotationValue( model )?.ApiVersion;
-
if ( apiVersion == null )
{
- return routeConstraint;
+ return new ODataPathRouteConstraint( versionedRouteName );
}
versionedRouteName += "-" + apiVersion.ToString();
- return new VersionedODataPathRouteConstraint( pathHandler, model, versionedRouteName, routeConventions.ToArray(), apiVersion );
+ return new VersionedODataPathRouteConstraint( versionedRouteName, apiVersion );
}
static void AddApiVersionConstraintIfNecessary( ODataRoute route )
@@ -412,18 +677,96 @@ static void AddApiVersionConstraintIfNecessary( ODataRoute route )
}
}
- static void AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch( string routeName, string routePrefix, HttpRouteCollection routes, List odataRoutes, List unversionedConstraints )
+ static void AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch(
+ this HttpConfiguration configuration,
+ string routeName,
+ string routePrefix,
+ List odataRoutes,
+ List unversionedConstraints,
+ Action configureAction )
{
Contract.Requires( !IsNullOrEmpty( routeName ) );
- Contract.Requires( routes != null );
+ Contract.Requires( configuration != null );
Contract.Requires( odataRoutes != null );
Contract.Requires( unversionedConstraints != null );
+ Contract.Requires( configureAction != null );
var unversionedRoute = new ODataRoute( routePrefix, new UnversionedODataPathRouteConstraint( unversionedConstraints ) );
AddApiVersionConstraintIfNecessary( unversionedRoute );
- routes.Add( routeName + UnversionedRouteSuffix, unversionedRoute );
+ configuration.Routes.Add( routeName, unversionedRoute );
odataRoutes.Add( unversionedRoute );
+ configuration.CreateODataRootContainer( routeName, configureAction );
+ }
+
+ static ODataUrlKeyDelimiter GetUrlKeyDelimiter( this HttpConfiguration configuration )
+ {
+ Contract.Requires( configuration != null );
+
+ if ( configuration.Properties.TryGetValue( UrlKeyDelimiterKey, out var value ) )
+ {
+ return value as ODataUrlKeyDelimiter;
+ }
+
+ configuration.Properties[UrlKeyDelimiterKey] = null;
+ return null;
+ }
+
+ static IServiceProvider CreateODataRootContainer( this HttpConfiguration configuration, string routeName, Action configureAction )
+ {
+ var rootContainer = configuration.CreateRootContainerImplementation( configureAction );
+ configuration.SetODataRootContainer( routeName, rootContainer );
+ return rootContainer;
+ }
+
+ static void SetODataRootContainer( this HttpConfiguration configuration, string routeName, IServiceProvider rootContainer ) =>
+ configuration.GetRootContainerMappings()[routeName] = rootContainer;
+
+ static ConcurrentDictionary GetRootContainerMappings( this HttpConfiguration configuration ) =>
+ (ConcurrentDictionary) configuration.Properties.GetOrAdd( RootContainerMappingsKey, key => new ConcurrentDictionary() );
+
+ static IServiceProvider CreateRootContainerImplementation( this HttpConfiguration configuration, Action configureAction )
+ {
+ var builder = configuration.CreateContainerBuilderWithDefaultServices();
+
+ configureAction?.Invoke( builder );
+
+ var rootContainer = builder.BuildContainer();
+
+ if ( rootContainer == null )
+ {
+ throw new InvalidOperationException( SR.NullContainer );
+ }
+
+ return rootContainer;
+ }
+
+ static IContainerBuilder CreateContainerBuilderWithDefaultServices( this HttpConfiguration configuration )
+ {
+ IContainerBuilder builder;
+
+ if ( configuration.Properties.TryGetValue( ContainerBuilderFactoryKey, out var value ) )
+ {
+ var builderFactory = (Func) value;
+
+ builder = builderFactory();
+
+ if ( builder == null )
+ {
+ throw new InvalidOperationException( SR.NullContainerBuilder );
+ }
+ }
+ else
+ {
+ builder = new DefaultContainerBuilder();
+ }
+
+ builder.AddService( Singleton, sp => configuration );
+ builder.AddService( Singleton, sp => configuration.GetDefaultQuerySettings() );
+ builder.AddDefaultODataServices();
+ builder.AddDefaultWebApiServices();
+
+ return builder;
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/IContainerBuilderExtensions.cs b/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/IContainerBuilderExtensions.cs
new file mode 100644
index 00000000..b7ac2486
--- /dev/null
+++ b/src/Microsoft.AspNet.OData.Versioning/System.Web.Http/IContainerBuilderExtensions.cs
@@ -0,0 +1,97 @@
+namespace System.Web.Http
+{
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.OData;
+ using OData.Routing;
+ using System.Web.Http.Dispatcher;
+ using System.Web.OData.Formatter.Deserialization;
+ using System.Web.OData.Formatter.Serialization;
+ using System.Web.OData.Query;
+ using System.Web.OData.Query.Expressions;
+ using System.Web.OData.Query.Validators;
+ using System.Web.OData.Routing.Conventions;
+ using static Microsoft.OData.ServiceLifetime;
+
+ internal static class IContainerBuilderExtensions
+ {
+ internal static void InitializeAttributeRouting( this IServiceProvider serviceProvider ) => serviceProvider.GetServices();
+
+ internal static void AddDefaultWebApiServices( this IContainerBuilder builder )
+ {
+ builder.AddService( Singleton );
+ AddServicePrototypes( builder );
+ AddQueryValidators( builder );
+ AddSerializationProviders( builder );
+ AddDeserializerServices( builder );
+ AddSerializerServices( builder );
+ AddBinders( builder );
+ builder.AddService( Singleton, sp => sp.GetService()?.Services.GetAssembliesResolver() ?? new DefaultAssembliesResolver() );
+ }
+
+ static void AddServicePrototypes( IContainerBuilder builder )
+ {
+ builder.AddServicePrototype( new ODataMessageReaderSettings()
+ {
+ EnableMessageStreamDisposal = false,
+ MessageQuotas = new ODataMessageQuotas { MaxReceivedMessageSize = long.MaxValue },
+
+ } );
+
+ builder.AddServicePrototype( new ODataMessageWriterSettings
+ {
+ EnableMessageStreamDisposal = false,
+ MessageQuotas = new ODataMessageQuotas { MaxReceivedMessageSize = long.MaxValue },
+ } );
+ }
+
+ static void AddQueryValidators( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ }
+
+ static void AddSerializationProviders( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ }
+
+ static void AddDeserializerServices( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ }
+
+ static void AddSerializerServices( IContainerBuilder builder )
+ {
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ builder.AddService( Singleton );
+ }
+
+ static void AddBinders( IContainerBuilder builder )
+ {
+ builder.AddService( Scoped );
+ builder.AddService( Transient );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.OData.Versioning/Web.OData/Controllers/VersionedMetadataController.cs b/src/Microsoft.AspNet.OData.Versioning/Web.OData/Controllers/VersionedMetadataController.cs
index c59621ca..2b6928c3 100644
--- a/src/Microsoft.AspNet.OData.Versioning/Web.OData/Controllers/VersionedMetadataController.cs
+++ b/src/Microsoft.AspNet.OData.Versioning/Web.OData/Controllers/VersionedMetadataController.cs
@@ -4,9 +4,9 @@
using System.Net.Http;
using System.Web.Http;
using System.Web.OData;
- using static Microsoft.OData.Core.ODataConstants;
- using static Microsoft.OData.Core.ODataUtils;
- using static Microsoft.OData.Core.ODataVersion;
+ using static Microsoft.OData.ODataConstants;
+ using static Microsoft.OData.ODataUtils;
+ using static Microsoft.OData.ODataVersion;
using static System.Net.HttpStatusCode;
using static System.String;
diff --git a/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedAttributeRoutingConvention.cs b/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedAttributeRoutingConvention.cs
index 672c3975..9e132989 100644
--- a/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedAttributeRoutingConvention.cs
+++ b/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedAttributeRoutingConvention.cs
@@ -1,6 +1,6 @@
namespace Microsoft.Web.OData.Routing
{
- using Microsoft.OData.Edm;
+ using Microsoft.Web.Http;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
@@ -14,38 +14,62 @@
///
public class VersionedAttributeRoutingConvention : AttributeRoutingConvention
{
+ readonly ApiVersion apiVersion;
+
///
/// Initializes a new instance of the class.
///
- /// The EDM model associated with the routing convention.
+ /// The name of the route.
/// The current HTTP configuration.
- public VersionedAttributeRoutingConvention( IEdmModel model, HttpConfiguration configuration ) : base( model, configuration ) { }
+ /// The API version associated with the convention.
+ public VersionedAttributeRoutingConvention( string routeName, HttpConfiguration configuration, ApiVersion apiVersion )
+ : base( routeName, configuration )
+ {
+ Arg.NotNull( apiVersion, nameof( apiVersion ) );
+ this.apiVersion = apiVersion;
+ }
///
/// Initializes a new instance of the class.
///
- /// The EDM model associated with the routing convention.
+ /// The name of the route.
/// The current HTTP configuration.
/// The OData path template handler associated with the routing convention.
- public VersionedAttributeRoutingConvention( IEdmModel model, HttpConfiguration configuration, IODataPathTemplateHandler pathTemplateHandler )
- : base( model, configuration, pathTemplateHandler ) { }
+ /// The API version associated with the convention.
+ public VersionedAttributeRoutingConvention( string routeName, HttpConfiguration configuration, IODataPathTemplateHandler pathTemplateHandler, ApiVersion apiVersion )
+ : base( routeName, configuration, pathTemplateHandler )
+ {
+ Arg.NotNull( apiVersion, nameof( apiVersion ) );
+ this.apiVersion = apiVersion;
+ }
///
/// Initializes a new instance of the class.
///
- /// The EDM model associated with the routing convention.
+ /// The name of the route.
/// The sequence of controller descriptors
- public VersionedAttributeRoutingConvention( IEdmModel model, IEnumerable controllers ) : base( model, controllers ) { }
+ /// The API version associated with the convention.
+ public VersionedAttributeRoutingConvention( string routeName, IEnumerable controllers, ApiVersion apiVersion )
+ : base( routeName, controllers )
+ {
+ Arg.NotNull( apiVersion, nameof( apiVersion ) );
+ this.apiVersion = apiVersion;
+ }
///
/// Initializes a new instance of the class.
///
- /// The EDM model associated with the routing convention.
+ /// The name of the route.
/// The sequence of controller descriptors
/// associated with the routing convention.
/// The OData path template handler associated with the routing convention.
- public VersionedAttributeRoutingConvention( IEdmModel model, IEnumerable controllers, IODataPathTemplateHandler pathTemplateHandler )
- : base( model, controllers, pathTemplateHandler ) { }
+ /// The API version associated with the convention.
+ public VersionedAttributeRoutingConvention( string routeName, IEnumerable controllers, IODataPathTemplateHandler pathTemplateHandler, ApiVersion apiVersion )
+ : base( routeName, controllers, pathTemplateHandler )
+ {
+ Arg.NotNull( apiVersion, nameof( apiVersion ) );
+ this.apiVersion = apiVersion;
+ }
///
/// Returns a value indicating whether the specified controller should be mapped using attribute routing conventions.
@@ -65,8 +89,6 @@ public override bool ShouldMapController( HttpControllerDescriptor controller )
return true;
}
- var apiVersion = Model.GetAnnotationValue( Model )?.ApiVersion;
-
return apiVersion != null && versionModel.DeclaredApiVersions.Contains( apiVersion );
}
}
diff --git a/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedODataPathRouteConstraint.cs b/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedODataPathRouteConstraint.cs
index b604cb7d..dc76b4a4 100644
--- a/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedODataPathRouteConstraint.cs
+++ b/src/Microsoft.AspNet.OData.Versioning/Web.OData/Routing/VersionedODataPathRouteConstraint.cs
@@ -2,8 +2,7 @@
{
using Http;
using Http.Versioning;
- using Microsoft.OData.Core;
- using Microsoft.OData.Edm;
+ using Microsoft.OData;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
@@ -11,7 +10,6 @@
using System.Web.Http;
using System.Web.Http.Routing;
using System.Web.OData.Routing;
- using System.Web.OData.Routing.Conventions;
using static System.Net.HttpStatusCode;
using static System.Web.Http.Routing.HttpRouteDirection;
@@ -23,30 +21,14 @@ public class VersionedODataPathRouteConstraint : ODataPathRouteConstraint
///
/// Initializes a new instance of the class.
///
- /// The OData path handler to use for parsing.
- /// The EDM model to use for parsing the path.
/// The name of the route this constraint is associated with.
- /// The OData routing conventions to use for selecting the controller name.
/// The API version associated with the route constraint.
- public VersionedODataPathRouteConstraint(
- IODataPathHandler pathHandler,
- IEdmModel model,
- string routeName,
- IEnumerable routingConventions,
- ApiVersion apiVersion )
- : base( pathHandler, model, routeName, routingConventions )
+ public VersionedODataPathRouteConstraint( string routeName, ApiVersion apiVersion ) : base( routeName )
{
Arg.NotNull( apiVersion, nameof( apiVersion ) );
ApiVersion = apiVersion;
}
- static bool IsServiceDocumentOrMetadataRoute( IDictionary values )
- {
- Contract.Requires( values != null );
- object value;
- return values.TryGetValue( "odataPath", out value ) && ( value == null || Equals( value, "$metadata" ) );
- }
-
///
/// Gets the API version matched by the current OData path route constraint.
///
@@ -103,6 +85,9 @@ public override bool Match( HttpRequestMessage request, IHttpRoute route, string
return false;
}
+ static bool IsServiceDocumentOrMetadataRoute( IDictionary values ) =>
+ values.TryGetValue( "odataPath", out var value ) && ( value == null || Equals( value, "$metadata" ) );
+
static ApiVersion GetRequestedApiVersionOrReturnBadRequest( HttpRequestMessage request, ApiVersionRequestProperties properties )
{
Contract.Requires( request != null );
diff --git a/test/Microsoft.AspNet.OData.Versioning.Tests/Microsoft.AspNet.OData.Versioning.Tests.csproj b/test/Microsoft.AspNet.OData.Versioning.Tests/Microsoft.AspNet.OData.Versioning.Tests.csproj
index f846c3f4..8b556869 100644
--- a/test/Microsoft.AspNet.OData.Versioning.Tests/Microsoft.AspNet.OData.Versioning.Tests.csproj
+++ b/test/Microsoft.AspNet.OData.Versioning.Tests/Microsoft.AspNet.OData.Versioning.Tests.csproj
@@ -3,6 +3,7 @@
net452
Microsoft.AspNet.OData.Versioning.Tests
+ Microsoft
diff --git a/test/Microsoft.AspNet.OData.Versioning.Tests/System.Web.OData/HttpConfigurationExtensionsTest.cs b/test/Microsoft.AspNet.OData.Versioning.Tests/System.Web.OData/HttpConfigurationExtensionsTest.cs
index c0b84d62..5f6229cf 100644
--- a/test/Microsoft.AspNet.OData.Versioning.Tests/System.Web.OData/HttpConfigurationExtensionsTest.cs
+++ b/test/Microsoft.AspNet.OData.Versioning.Tests/System.Web.OData/HttpConfigurationExtensionsTest.cs
@@ -13,29 +13,21 @@
using Microsoft.Web.OData.Routing;
using Moq;
using Routing.Conventions;
+ using System.Collections.Concurrent;
+ using System.Web.Http.Routing;
+ using System.Web.OData.Routing;
using Xunit;
public class HttpConfigurationExtensionsTest
{
+ const string RootContainerMappingsKey = "System.Web.OData.RootContainerMappingsKey";
+
[ApiVersion( "1.0" )]
sealed class ControllerV1 : ODataController { }
[ApiVersion( "2.0" )]
sealed class ControllerV2 : ODataController { }
- static IEnumerable CreateModels( HttpConfiguration configuration )
- {
- var controllerTypeResolver = new Mock();
- var controllerTypes = new List() { typeof( ControllerV1 ), typeof( ControllerV2 ) };
-
- controllerTypeResolver.Setup( ctr => ctr.GetControllerTypes( It.IsAny() ) ).Returns( controllerTypes );
- configuration.Services.Replace( typeof( IHttpControllerTypeResolver ), controllerTypeResolver.Object );
-
- var builder = new VersionedODataModelBuilder( configuration );
-
- return builder.GetEdmModels();
- }
-
[Fact]
public void map_versioned_odata_routes_should_return_expected_result()
{
@@ -50,13 +42,14 @@ public void map_versioned_odata_routes_should_return_expected_result()
// act
var route = configuration.MapVersionedODataRoute( routeName, routePrefix, model, apiVersion, batchHandler );
- var constraint = (VersionedODataPathRouteConstraint) route.PathRouteConstraint;
+ var constraint = route.PathRouteConstraint;
+ var routingConventions = GetRoutingConventions( configuration, route );
var batchRoute = configuration.Routes["odataBatch"];
// assert
- constraint.RoutingConventions[0].Should().BeOfType();
- constraint.RoutingConventions[1].Should().BeOfType();
- constraint.RoutingConventions.OfType().Should().BeEmpty();
+ routingConventions[0].Should().BeOfType();
+ routingConventions[1].Should().BeOfType();
+ routingConventions.OfType().Should().BeEmpty();
constraint.RouteName.Should().Be( routeName );
route.RoutePrefix.Should().Be( routePrefix );
batchRoute.Handler.Should().Be( batchHandler );
@@ -88,12 +81,13 @@ public void map_versioned_odata_routes_should_return_expected_results()
continue;
}
- var apiVersion = constraint.EdmModel.GetAnnotationValue( constraint.EdmModel ).ApiVersion;
+ var apiVersion = constraint.ApiVersion;
+ var routingConventions = GetRoutingConventions( configuration, route );
var versionedRouteName = routeName + "-" + apiVersion.ToString();
- constraint.RoutingConventions[0].Should().BeOfType();
- constraint.RoutingConventions[1].Should().BeOfType();
- constraint.RoutingConventions.OfType().Should().BeEmpty();
+ routingConventions[0].Should().BeOfType();
+ routingConventions[1].Should().BeOfType();
+ routingConventions.OfType().Should().BeEmpty();
constraint.RouteName.Should().Be( versionedRouteName );
route.RoutePrefix.Should().Be( routePrefix );
}
@@ -101,5 +95,32 @@ public void map_versioned_odata_routes_should_return_expected_results()
batchRoute.Handler.Should().Be( batchHandler );
batchRoute.RouteTemplate.Should().Be( "api/$batch" );
}
+
+ static IEnumerable CreateModels( HttpConfiguration configuration )
+ {
+ var controllerTypeResolver = new Mock();
+ var controllerTypes = new List() { typeof( ControllerV1 ), typeof( ControllerV2 ) };
+
+ controllerTypeResolver.Setup( ctr => ctr.GetControllerTypes( It.IsAny() ) ).Returns( controllerTypes );
+ configuration.Services.Replace( typeof( IHttpControllerTypeResolver ), controllerTypeResolver.Object );
+
+ var builder = new VersionedODataModelBuilder( configuration );
+
+ return builder.GetEdmModels();
+ }
+
+ static IReadOnlyList GetRoutingConventions( HttpConfiguration configuration, ODataRoute route )
+ {
+ var routes = configuration.Routes;
+ var pairs = new KeyValuePair[routes.Count];
+
+ routes.CopyTo( pairs, 0 );
+
+ var key = pairs.Single( p => p.Value == route ).Key;
+ var serviceProviders = (ConcurrentDictionary) configuration.Properties[RootContainerMappingsKey];
+ var routingConventions = (IEnumerable) serviceProviders[key].GetService( typeof( IEnumerable ) );
+
+ return routingConventions.ToArray();
+ }
}
}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.OData.Versioning.Tests/Test.cs b/test/Microsoft.AspNet.OData.Versioning.Tests/Test.cs
new file mode 100644
index 00000000..6cc35f95
--- /dev/null
+++ b/test/Microsoft.AspNet.OData.Versioning.Tests/Test.cs
@@ -0,0 +1,22 @@
+namespace Microsoft
+{
+ using Microsoft.OData.Edm;
+ using System;
+ using System.Web.OData.Builder;
+
+ internal static class Test
+ {
+ static Test()
+ {
+ var builder = new ODataModelBuilder();
+ var tests = builder.EntitySet( "Tests" ).EntityType;
+
+ tests.HasKey( t => t.Id );
+ Model = builder.GetEdmModel();
+ }
+
+ internal static IEdmModel Model { get; }
+
+ internal static IEdmModel EmptyModel { get; } = new ODataModelBuilder().GetEdmModel();
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.OData.Versioning.Tests/TestEntity.cs b/test/Microsoft.AspNet.OData.Versioning.Tests/TestEntity.cs
new file mode 100644
index 00000000..4391cb2c
--- /dev/null
+++ b/test/Microsoft.AspNet.OData.Versioning.Tests/TestEntity.cs
@@ -0,0 +1,9 @@
+namespace Microsoft
+{
+ using System;
+
+ public class TestEntity
+ {
+ public int Id { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedAttributeRoutingConventionTest.cs b/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedAttributeRoutingConventionTest.cs
index 846188e0..2de2993b 100644
--- a/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedAttributeRoutingConventionTest.cs
+++ b/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedAttributeRoutingConventionTest.cs
@@ -12,7 +12,6 @@
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.OData;
- using System.Web.OData.Builder;
using Xunit;
public class VersionedAttributeRoutingConventionTest
@@ -40,12 +39,9 @@ static IEdmModel CreateModel( HttpConfiguration configuration, Type controllerTy
public void should_map_controller_should_return_true_for_versionX2Dneutral_controller()
{
// arrange
- var model = new ODataModelBuilder().GetEdmModel();
- var controller = new HttpControllerDescriptor( new HttpConfiguration(), string.Empty, typeof( NeutralController ) );
- var convention = new VersionedAttributeRoutingConvention( model, new HttpControllerDescriptor[0] );
- var annotation = new ApiVersionAnnotation( new ApiVersion( 1, 0 ) );
-
- model.SetAnnotationValue( model, annotation );
+ var configuration = new HttpConfiguration();
+ var controller = new HttpControllerDescriptor( configuration, string.Empty, typeof( NeutralController ) );
+ var convention = new VersionedAttributeRoutingConvention( "Tests", configuration, new ApiVersion( 1, 0 ) );
// act
var result = convention.ShouldMapController( controller );
@@ -60,12 +56,9 @@ public void should_map_controller_should_return_true_for_versionX2Dneutral_contr
public void should_map_controller_should_return_expected_result_for_controller_version( int majorVersion, bool expected )
{
// arrange
- var model = new ODataModelBuilder().GetEdmModel();
- var controller = new HttpControllerDescriptor( new HttpConfiguration(), string.Empty, typeof( ControllerV1 ) );
- var convention = new VersionedAttributeRoutingConvention( model, new HttpControllerDescriptor[0] );
- var annotation = new ApiVersionAnnotation( new ApiVersion( majorVersion, 0 ) );
-
- model.SetAnnotationValue( model, annotation );
+ var configuration = new HttpConfiguration();
+ var controller = new HttpControllerDescriptor( configuration, string.Empty, typeof( ControllerV1 ) );
+ var convention = new VersionedAttributeRoutingConvention( "Tests", configuration, new ApiVersion( majorVersion, 0 ) );
// act
var result = convention.ShouldMapController( controller );
diff --git a/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedMetadataRoutingConventionTest.cs b/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedMetadataRoutingConventionTest.cs
index 917d1b7b..3b25e6c1 100644
--- a/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedMetadataRoutingConventionTest.cs
+++ b/test/Microsoft.AspNet.OData.Versioning.Tests/Web.OData/Routing/VersionedMetadataRoutingConventionTest.cs
@@ -1,24 +1,44 @@
namespace Microsoft.Web.OData.Routing
{
using FluentAssertions;
+ using Microsoft.OData;
+ using Microsoft.OData.Edm;
using Moq;
+ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Controllers;
+ using System.Web.OData;
using System.Web.OData.Routing;
using Xunit;
+ using static Microsoft.OData.ServiceLifetime;
+ using ODataPath = System.Web.OData.Routing.ODataPath;
public class VersionedMetadataRoutingConventionTest
{
+ readonly IODataPathHandler pathHandler = new DefaultODataPathHandler();
+ readonly IServiceProvider serviceProvider;
+
+ public VersionedMetadataRoutingConventionTest()
+ {
+ var builder = new DefaultContainerBuilder();
+
+ builder.AddDefaultODataServices();
+ builder.AddService( Singleton, typeof( IEdmModel ), sp => Test.Model );
+ serviceProvider = builder.BuildContainer();
+ }
+
+ ODataPath ParseUrl( string odataPath ) => pathHandler.Parse( "http://localhost", odataPath, serviceProvider );
+
public static IEnumerable