diff --git a/samples/Mvc.Server/Startup.cs b/samples/Mvc.Server/Startup.cs
index 54ce2cf4..4e28596e 100644
--- a/samples/Mvc.Server/Startup.cs
+++ b/samples/Mvc.Server/Startup.cs
@@ -66,10 +66,10 @@ namespace Mvc.Server
// Register the OpenIddict server services.
.AddServer(options =>
{
- // Register the ASP.NET Core MVC binder used by OpenIddict.
+ // Register the ASP.NET Core MVC services used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
- options.AddMvcBinders();
+ options.UseMvc();
// Enable the authorization, logout, token and userinfo endpoints.
options.EnableAuthorizationEndpoint("/connect/authorize")
diff --git a/src/OpenIddict.Mvc/OpenIddictExtensions.cs b/src/OpenIddict.Mvc/OpenIddictExtensions.cs
deleted file mode 100644
index abe2f8d4..00000000
--- a/src/OpenIddict.Mvc/OpenIddictExtensions.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- * See https://github.com/openiddict/openiddict-core for more information concerning
- * the license and the contributors participating to this project.
- */
-
-using System;
-using JetBrains.Annotations;
-using Microsoft.AspNetCore.Mvc;
-using OpenIddict.Mvc;
-
-namespace Microsoft.Extensions.DependencyInjection
-{
- public static class OpenIddictExtensions
- {
- ///
- /// Registers the ASP.NET Core MVC model binders used by OpenIddict.
- ///
- /// The services builder used by OpenIddict to register new services.
- /// This extension can be safely called multiple times.
- /// The .
- public static OpenIddictServerBuilder AddMvcBinders([NotNull] this OpenIddictServerBuilder builder)
- {
- if (builder == null)
- {
- throw new ArgumentNullException(nameof(builder));
- }
-
- builder.Services.Configure(options =>
- {
- // Skip the binder registration if it was already added to the providers collection.
- for (var index = 0; index < options.ModelBinderProviders.Count; index++)
- {
- var provider = options.ModelBinderProviders[index];
- if (provider is OpenIddictModelBinder)
- {
- return;
- }
- }
-
- options.ModelBinderProviders.Insert(0, new OpenIddictModelBinder());
- });
-
- return builder;
- }
- }
-}
\ No newline at end of file
diff --git a/src/OpenIddict.Mvc/OpenIddictModelBinder.cs b/src/OpenIddict.Mvc/OpenIddictMvcBinder.cs
similarity index 56%
rename from src/OpenIddict.Mvc/OpenIddictModelBinder.cs
rename to src/OpenIddict.Mvc/OpenIddictMvcBinder.cs
index 9a716717..ed78e4d0 100644
--- a/src/OpenIddict.Mvc/OpenIddictModelBinder.cs
+++ b/src/OpenIddict.Mvc/OpenIddictMvcBinder.cs
@@ -1,10 +1,18 @@
-using System;
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using System;
+using System.Text;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Primitives;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
+using Microsoft.Extensions.Options;
namespace OpenIddict.Mvc
{
@@ -13,8 +21,15 @@ namespace OpenIddict.Mvc
/// and
/// instances.
///
- public class OpenIddictModelBinder : IModelBinder, IModelBinderProvider
+ public class OpenIddictMvcBinder : IModelBinder
{
+ private readonly IOptions _options;
+
+ public OpenIddictMvcBinder([NotNull] IOptions options)
+ {
+ _options = options;
+ }
+
///
/// Tries to bind a model from the request.
///
@@ -30,20 +45,25 @@ namespace OpenIddict.Mvc
if (context.ModelType == typeof(OpenIdConnectRequest))
{
var request = context.HttpContext.GetOpenIdConnectRequest();
- if (request == null)
+ if (request == null && !_options.Value.DisableBindingExceptions)
{
- throw new InvalidOperationException("The OpenID Connect request cannot be retrieved from the ASP.NET context. " +
- "Make sure that 'app.UseOpenIddict()' is called before 'app.UseMvc()' and " +
- "that the action route corresponds to the endpoint path registered via " +
- "'services.AddOpenIddict().Enable[...]Endpoint(...)'.");
+ throw new InvalidOperationException(new StringBuilder()
+ .AppendLine("The OpenID Connect request cannot be retrieved from the ASP.NET context.")
+ .Append("Make sure that 'app.UseOpenIddictServer()' is called before 'app.UseMvc()' ")
+ .Append("and that the action route corresponds to the endpoint path registered via ")
+ .Append("'services.AddOpenIddict().AddServer().Enable[...]Endpoint(...)'.")
+ .ToString());
}
- // Add a new validation state entry to prevent the built-in
- // model validators from validating the OpenID Connect request.
- context.ValidationState.Add(request, new ValidationStateEntry
+ if (request != null)
{
- SuppressValidation = true
- });
+ // Add a new validation state entry to prevent the built-in
+ // model validators from validating the OpenID Connect request.
+ context.ValidationState.Add(request, new ValidationStateEntry
+ {
+ SuppressValidation = true
+ });
+ }
context.Result = ModelBindingResult.Success(request);
@@ -70,26 +90,5 @@ namespace OpenIddict.Mvc
throw new InvalidOperationException("The specified model type is not supported by this binder.");
}
-
- ///
- /// Tries to resolve the model binder corresponding to the given model.
- ///
- /// The model binding context.
- /// The current instance or null if the model is not supported.
- public IModelBinder GetBinder([NotNull] ModelBinderProviderContext context)
- {
- if (context == null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
- if (context.Metadata.ModelType == typeof(OpenIdConnectRequest) ||
- context.Metadata.ModelType == typeof(OpenIdConnectResponse))
- {
- return this;
- }
-
- return null;
- }
}
}
diff --git a/src/OpenIddict.Mvc/OpenIddictMvcBinderProvider.cs b/src/OpenIddict.Mvc/OpenIddictMvcBinderProvider.cs
new file mode 100644
index 00000000..167c0c8f
--- /dev/null
+++ b/src/OpenIddict.Mvc/OpenIddictMvcBinderProvider.cs
@@ -0,0 +1,42 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using System;
+using AspNet.Security.OpenIdConnect.Primitives;
+using JetBrains.Annotations;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
+
+namespace OpenIddict.Mvc
+{
+ ///
+ /// Represents an ASP.NET Core MVC model binder provider that is
+ /// able to provide instances of .
+ ///
+ public class OpenIddictMvcBinderProvider : IModelBinderProvider
+ {
+ ///
+ /// Tries to resolve the model binder corresponding to the given model.
+ ///
+ /// The model binding context.
+ /// The current instance or null if the model is not supported.
+ public IModelBinder GetBinder([NotNull] ModelBinderProviderContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ if (context.Metadata.ModelType == typeof(OpenIdConnectRequest) ||
+ context.Metadata.ModelType == typeof(OpenIdConnectResponse))
+ {
+ return new BinderTypeModelBinder(typeof(OpenIddictMvcBinder));
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs b/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs
new file mode 100644
index 00000000..e7555294
--- /dev/null
+++ b/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using System;
+using System.ComponentModel;
+using AspNet.Security.OpenIdConnect.Primitives;
+using JetBrains.Annotations;
+using OpenIddict.Mvc;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ ///
+ /// Exposes the necessary methods required to configure the OpenIddict MVC integration.
+ ///
+ public class OpenIddictMvcBuilder
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The services collection.
+ public OpenIddictMvcBuilder([NotNull] IServiceCollection services)
+ {
+ if (services == null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ Services = services;
+ }
+
+ ///
+ /// Gets the services collection.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public IServiceCollection Services { get; }
+
+ ///
+ /// Amends the default OpenIddict MVC configuration.
+ ///
+ /// The delegate used to configure the OpenIddict options.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public OpenIddictMvcBuilder Configure([NotNull] Action configuration)
+ {
+ if (configuration == null)
+ {
+ throw new ArgumentNullException(nameof(configuration));
+ }
+
+ Services.Configure(configuration);
+
+ return this;
+ }
+
+ ///
+ /// Configures the OpenIddict MVC binder to avoid throwing an exception
+ /// when it is unable to bind
+ /// parameters (e.g because the endpoint is not an OpenID Connect endpoint).
+ ///
+ /// The .
+ public OpenIddictMvcBuilder DisableBindingExceptions()
+ => Configure(options => options.DisableBindingExceptions = true);
+ }
+}
diff --git a/src/OpenIddict.Mvc/OpenIddictMvcExtensions.cs b/src/OpenIddict.Mvc/OpenIddictMvcExtensions.cs
new file mode 100644
index 00000000..a689e1ca
--- /dev/null
+++ b/src/OpenIddict.Mvc/OpenIddictMvcExtensions.cs
@@ -0,0 +1,157 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using System;
+using JetBrains.Annotations;
+using Microsoft.AspNetCore.Mvc;
+using OpenIddict.Mvc;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class OpenIddictMvcExtensions
+ {
+ ///
+ /// Registers the ASP.NET Core MVC services used by OpenIddict.
+ ///
+ /// The services builder used by OpenIddict to register new services.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public static OpenIddictMvcBuilder UseMvc([NotNull] this OpenIddictServerBuilder builder)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ return RegisterMvcServices(builder.Services);
+ }
+
+ ///
+ /// Registers the ASP.NET Core MVC model binders used by OpenIddict.
+ ///
+ /// The services builder used by OpenIddict to register new services.
+ /// The configuration delegate used to configure the MVC services.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public static OpenIddictServerBuilder UseMvc(
+ [NotNull] this OpenIddictServerBuilder builder,
+ [NotNull] Action configuration)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ configuration(builder.UseMvc());
+
+ return builder;
+ }
+
+ ///
+ /// Registers the ASP.NET Core MVC services used by OpenIddict.
+ ///
+ /// The services builder used by ASP.NET Core MVC to register new services.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public static OpenIddictMvcBuilder UseOpenIddict([NotNull] this IMvcCoreBuilder builder)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ return RegisterMvcServices(builder.Services);
+ }
+
+ ///
+ /// Registers the ASP.NET Core MVC model binders used by OpenIddict.
+ ///
+ /// The services builder used by ASP.NET Core MVC to register new services.
+ /// The configuration delegate used to configure the MVC services.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public static IMvcCoreBuilder UseOpenIddict(
+ [NotNull] this IMvcCoreBuilder builder,
+ [NotNull] Action configuration)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ configuration(builder.UseOpenIddict());
+
+ return builder;
+ }
+
+ ///
+ /// Registers the ASP.NET Core MVC services used by OpenIddict.
+ ///
+ /// The services builder used by ASP.NET Core MVC to register new services.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public static OpenIddictMvcBuilder UseOpenIddict([NotNull] this IMvcBuilder builder)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ return RegisterMvcServices(builder.Services);
+ }
+
+ ///
+ /// Registers the ASP.NET Core MVC model binders used by OpenIddict.
+ ///
+ /// The services builder used by ASP.NET Core MVC to register new services.
+ /// The configuration delegate used to configure the MVC services.
+ /// This extension can be safely called multiple times.
+ /// The .
+ public static IMvcBuilder UseOpenIddict(
+ [NotNull] this IMvcBuilder builder,
+ [NotNull] Action configuration)
+ {
+ if (builder == null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ configuration(builder.UseOpenIddict());
+
+ return builder;
+ }
+
+ ///
+ /// Registers the ASP.NET Core MVC services used by OpenIddict.
+ ///
+ /// The services collection.
+ /// The .
+ private static OpenIddictMvcBuilder RegisterMvcServices([NotNull] IServiceCollection services)
+ {
+ if (services == null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ services.Configure(options =>
+ {
+ // Skip the binder registration if it was already added to the providers collection.
+ for (var index = 0; index < options.ModelBinderProviders.Count; index++)
+ {
+ var provider = options.ModelBinderProviders[index];
+ if (provider is OpenIddictMvcBinderProvider)
+ {
+ return;
+ }
+ }
+
+ options.ModelBinderProviders.Insert(0, new OpenIddictMvcBinderProvider());
+ });
+
+ return new OpenIddictMvcBuilder(services);
+ }
+ }
+}
diff --git a/src/OpenIddict.Mvc/OpenIddictMvcOptions.cs b/src/OpenIddict.Mvc/OpenIddictMvcOptions.cs
new file mode 100644
index 00000000..e4e1e820
--- /dev/null
+++ b/src/OpenIddict.Mvc/OpenIddictMvcOptions.cs
@@ -0,0 +1,24 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using AspNet.Security.OpenIdConnect.Primitives;
+
+namespace OpenIddict.Mvc
+{
+ ///
+ /// Provides various settings needed to configure the OpenIddict MVC integration.
+ ///
+ public class OpenIddictMvcOptions
+ {
+ ///
+ /// Gets or sets a boolean indicating whether the OpenIddict MVC binder should throw
+ /// an exception when it is unable to bind
+ /// parameters (e.g because the endpoint is not an OpenID Connect endpoint).
+ /// If exceptions are disabled, the model is automatically set to null.
+ ///
+ public bool DisableBindingExceptions { get; set; }
+ }
+}
diff --git a/src/OpenIddict/OpenIddict.csproj b/src/OpenIddict/OpenIddict.csproj
index 8abbcdaf..f205027f 100644
--- a/src/OpenIddict/OpenIddict.csproj
+++ b/src/OpenIddict/OpenIddict.csproj
@@ -3,7 +3,7 @@
- net451;netstandard1.4
+ net451;netstandard1.6
@@ -14,6 +14,7 @@
+
diff --git a/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkExtensionsTests.cs b/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkExtensionsTests.cs
index b0bbdc61..e2e00596 100644
--- a/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkExtensionsTests.cs
+++ b/test/OpenIddict.EntityFramework.Tests/OpenIddictEntityFrameworkExtensionsTests.cs
@@ -8,7 +8,6 @@ using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OpenIddict.Core;
-using OpenIddict.EntityFramework;
using OpenIddict.EntityFramework.Models;
using Xunit;
@@ -24,8 +23,8 @@ namespace OpenIddict.EntityFramework.Tests
public void AddEntityFrameworkStores_RegistersEntityFrameworkStoreFactories(Type type)
{
// Arrange
- var services = new ServiceCollection();
- var builder = services.AddOpenIddict().AddCore();
+ var services = new ServiceCollection().AddOptions();
+ var builder = new OpenIddictCoreBuilder(services);
// Act
builder.UseEntityFramework();
@@ -38,8 +37,8 @@ namespace OpenIddict.EntityFramework.Tests
public void UseEntityFrameworkModels_KeyTypeDefaultsToString()
{
// Arrange
- var services = new ServiceCollection();
- var builder = services.AddOpenIddict().AddCore();
+ var services = new ServiceCollection().AddOptions();
+ var builder = new OpenIddictCoreBuilder(services);
// Act
builder.UseEntityFramework();
diff --git a/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreExtensionsTests.cs b/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreExtensionsTests.cs
index 2964ac81..18cd76bf 100644
--- a/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreExtensionsTests.cs
+++ b/test/OpenIddict.EntityFrameworkCore.Tests/OpenIddictEntityFrameworkCoreExtensionsTests.cs
@@ -23,8 +23,8 @@ namespace OpenIddict.EntityFrameworkCore.Tests
public void UseEntityFrameworkCore_RegistersEntityFrameworkCoreStoreFactories(Type type)
{
// Arrange
- var services = new ServiceCollection();
- var builder = services.AddOpenIddict().AddCore();
+ var services = new ServiceCollection().AddOptions();
+ var builder = new OpenIddictCoreBuilder(services);
// Act
builder.UseEntityFrameworkCore();
@@ -37,8 +37,8 @@ namespace OpenIddict.EntityFrameworkCore.Tests
public void UseEntityFrameworkCore_KeyTypeDefaultsToString()
{
// Arrange
- var services = new ServiceCollection();
- var builder = services.AddOpenIddict().AddCore();
+ var services = new ServiceCollection().AddOptions();
+ var builder = new OpenIddictCoreBuilder(services);
// Act
builder.UseEntityFrameworkCore();
@@ -57,8 +57,8 @@ namespace OpenIddict.EntityFrameworkCore.Tests
public void UseEntityFrameworkCore_KeyTypeCanBeOverriden()
{
// Arrange
- var services = new ServiceCollection();
- var builder = services.AddOpenIddict().AddCore();
+ var services = new ServiceCollection().AddOptions();
+ var builder = new OpenIddictCoreBuilder(services);
// Act
builder.UseEntityFrameworkCore().ReplaceDefaultEntities();
diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictExtensionsTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictExtensionsTests.cs
deleted file mode 100644
index 5aa9c286..00000000
--- a/test/OpenIddict.Mvc.Tests/OpenIddictExtensionsTests.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
- * See https://github.com/openiddict/openiddict-core for more information concerning
- * the license and the contributors participating to this project.
- */
-
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
-using Xunit;
-
-namespace OpenIddict.Mvc.Tests
-{
- public class OpenIddictExtensionsTests
- {
- [Fact]
- public void AddMvcBinders_RegistersModelBinderProvider()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddOptions();
-
- var builder = services.AddOpenIddict().AddServer();
-
- // Act
- builder.AddMvcBinders();
-
- var provider = services.BuildServiceProvider();
- var options = provider.GetRequiredService>();
-
- // Assert
- Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictModelBinder);
- }
- }
-}
diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictMvcBuilderTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictMvcBuilderTests.cs
new file mode 100644
index 00000000..4999240c
--- /dev/null
+++ b/test/OpenIddict.Mvc.Tests/OpenIddictMvcBuilderTests.cs
@@ -0,0 +1,43 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace OpenIddict.Mvc.Tests
+{
+ public class OpenIddictMvcBuilderTests
+ {
+ [Fact]
+ public void Configure_OptionsAreCorrectlyAmended()
+ {
+ // Arrange
+ var services = CreateServices();
+ var builder = CreateBuilder(services);
+
+ // Act
+ builder.Configure(configuration => configuration.DisableBindingExceptions = true);
+
+ var options = GetOptions(services);
+
+ // Assert
+ Assert.True(options.DisableBindingExceptions);
+ }
+
+ private static IServiceCollection CreateServices()
+ => new ServiceCollection().AddOptions();
+
+ private static OpenIddictMvcBuilder CreateBuilder(IServiceCollection services)
+ => new OpenIddictMvcBuilder(services);
+
+ private static OpenIddictMvcOptions GetOptions(IServiceCollection services)
+ {
+ var provider = services.BuildServiceProvider();
+ return provider.GetRequiredService>().Value;
+ }
+ }
+}
diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictMvcExtensionsTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictMvcExtensionsTests.cs
new file mode 100644
index 00000000..5d702844
--- /dev/null
+++ b/test/OpenIddict.Mvc.Tests/OpenIddictMvcExtensionsTests.cs
@@ -0,0 +1,75 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
+using Microsoft.AspNetCore.Mvc.Internal;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using Xunit;
+
+namespace OpenIddict.Mvc.Tests
+{
+ public class OpenIddictMvcExtensionsTests
+ {
+ [Fact]
+ public void UseMvc_RegistersModelBinderProvider()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ services.AddOptions();
+
+ var builder = new OpenIddictServerBuilder(services);
+
+ // Act
+ builder.UseMvc();
+
+ var provider = services.BuildServiceProvider();
+ var options = provider.GetRequiredService>();
+
+ // Assert
+ Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictMvcBinderProvider);
+ }
+
+ [Fact]
+ public void UseOpenIddict_MvcCoreBuilder_RegistersModelBinderProvider()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ services.AddOptions();
+
+ var builder = new MvcCoreBuilder(services, new ApplicationPartManager());
+
+ // Act
+ builder.UseOpenIddict();
+
+ var provider = services.BuildServiceProvider();
+ var options = provider.GetRequiredService>();
+
+ // Assert
+ Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictMvcBinderProvider);
+ }
+
+ [Fact]
+ public void UseOpenIddict_MvcBuilder_RegistersModelBinderProvider()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ services.AddOptions();
+
+ var builder = new MvcBuilder(services, new ApplicationPartManager());
+
+ // Act
+ builder.UseOpenIddict();
+
+ var provider = services.BuildServiceProvider();
+ var options = provider.GetRequiredService>();
+
+ // Assert
+ Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictMvcBinderProvider);
+ }
+ }
+}
diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictMvcModelBinderProviderTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictMvcModelBinderProviderTests.cs
new file mode 100644
index 00000000..4d804bb2
--- /dev/null
+++ b/test/OpenIddict.Mvc.Tests/OpenIddictMvcModelBinderProviderTests.cs
@@ -0,0 +1,63 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using AspNet.Security.OpenIdConnect.Primitives;
+using AspNet.Security.OpenIdConnect.Server;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
+using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
+using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
+using Moq;
+using Xunit;
+
+namespace OpenIddict.Mvc.Tests
+{
+ public class OpenIddictMvcModelBinderProviderTests
+ {
+ [Theory]
+ [InlineData(typeof(object))]
+ [InlineData(typeof(IList))]
+ [InlineData(typeof(int[]))]
+ public void GetBinder_ReturnsNullForUnsupportedTypes(Type type)
+ {
+ // Arrange
+ var provider = new OpenIddictMvcBinderProvider();
+
+ var metadata = new Mock(ModelMetadataIdentity.ForType(type));
+
+ var context = new Mock();
+ context.Setup(mock => mock.Metadata)
+ .Returns(metadata.Object);
+
+ // Act and assert
+ Assert.Null(provider.GetBinder(context.Object));
+ }
+
+ [Theory]
+ [InlineData(typeof(OpenIdConnectRequest))]
+ [InlineData(typeof(OpenIdConnectResponse))]
+ public void GetBinder_ReturnsNonNullForSupportedTypes(Type type)
+ {
+ // Arrange
+ var provider = new OpenIddictMvcBinderProvider();
+
+ var metadata = new Mock(ModelMetadataIdentity.ForType(type));
+
+ var context = new Mock();
+ context.Setup(mock => mock.Metadata)
+ .Returns(metadata.Object);
+
+ // Act and assert
+ Assert.NotNull((BinderTypeModelBinder) provider.GetBinder(context.Object));
+ }
+ }
+}
diff --git a/test/OpenIddict.Mvc.Tests/OpenIddictModelBinderTests.cs b/test/OpenIddict.Mvc.Tests/OpenIddictMvcModelBinderTests.cs
similarity index 71%
rename from test/OpenIddict.Mvc.Tests/OpenIddictModelBinderTests.cs
rename to test/OpenIddict.Mvc.Tests/OpenIddictMvcModelBinderTests.cs
index 42f4182d..2e2fc29d 100644
--- a/test/OpenIddict.Mvc.Tests/OpenIddictModelBinderTests.cs
+++ b/test/OpenIddict.Mvc.Tests/OpenIddictMvcModelBinderTests.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.Text;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Primitives;
using AspNet.Security.OpenIdConnect.Server;
@@ -13,14 +14,13 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
-using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
-using Moq;
+using Microsoft.Extensions.Options;
using Xunit;
namespace OpenIddict.Mvc.Tests
{
- public class OpenIddictModelBinderTests
+ public class OpenIddictMvcModelBinderTests
{
[Theory]
[InlineData(typeof(object))]
@@ -29,7 +29,9 @@ namespace OpenIddict.Mvc.Tests
public async Task BindModelAsync_ThrowsAnExceptionForUnsupportedTypes(Type type)
{
// Arrange
- var binder = new OpenIddictModelBinder();
+ var options = Options.Create(new OpenIddictMvcOptions());
+
+ var binder = new OpenIddictMvcBinder(options);
var provider = new EmptyModelMetadataProvider();
var context = new DefaultModelBindingContext
@@ -50,7 +52,9 @@ namespace OpenIddict.Mvc.Tests
public async Task BindModelAsync_ThrowsAnExceptionWhenRequestCannotBeFound()
{
// Arrange
- var binder = new OpenIddictModelBinder();
+ var options = Options.Create(new OpenIddictMvcOptions());
+
+ var binder = new OpenIddictMvcBinder(options);
var provider = new EmptyModelMetadataProvider();
var context = new DefaultModelBindingContext
@@ -69,17 +73,51 @@ namespace OpenIddict.Mvc.Tests
return binder.BindModelAsync(context);
});
- Assert.Equal("The OpenID Connect request cannot be retrieved from the ASP.NET context. " +
- "Make sure that 'app.UseOpenIddict()' is called before 'app.UseMvc()' and " +
- "that the action route corresponds to the endpoint path registered via " +
- "'services.AddOpenIddict().Enable[...]Endpoint(...)'.", exception.Message);
+ Assert.Equal(new StringBuilder()
+ .AppendLine("The OpenID Connect request cannot be retrieved from the ASP.NET context.")
+ .Append("Make sure that 'app.UseOpenIddictServer()' is called before 'app.UseMvc()' ")
+ .Append("and that the action route corresponds to the endpoint path registered via ")
+ .Append("'services.AddOpenIddict().AddServer().Enable[...]Endpoint(...)'.")
+ .ToString(), exception.Message);
+ }
+
+ [Fact]
+ public async Task BindModelAsync_ReturnsNullWhenRequestCannotBeFoundAndExceptionsAreDisabled()
+ {
+ // Arrange
+ var options = Options.Create(new OpenIddictMvcOptions
+ {
+ DisableBindingExceptions = true
+ });
+
+ var binder = new OpenIddictMvcBinder(options);
+ var provider = new EmptyModelMetadataProvider();
+
+ var context = new DefaultModelBindingContext
+ {
+ ActionContext = new ActionContext()
+ {
+ HttpContext = new DefaultHttpContext(),
+ },
+
+ ModelMetadata = provider.GetMetadataForType(typeof(OpenIdConnectRequest))
+ };
+
+ // Act
+ await binder.BindModelAsync(context);
+
+ // Assert
+ Assert.True(context.Result.IsModelSet);
+ Assert.Null(context.Result.Model);
}
[Fact]
public async Task BindModelAsync_ReturnsNullWhenResponseCannotBeFound()
{
// Arrange
- var binder = new OpenIddictModelBinder();
+ var options = Options.Create(new OpenIddictMvcOptions());
+
+ var binder = new OpenIddictMvcBinder(options);
var provider = new EmptyModelMetadataProvider();
var context = new DefaultModelBindingContext
@@ -106,7 +144,9 @@ namespace OpenIddict.Mvc.Tests
public async Task BindModelAsync_ReturnsAmbientRequest()
{
// Arrange
- var binder = new OpenIddictModelBinder();
+ var options = Options.Create(new OpenIddictMvcOptions());
+
+ var binder = new OpenIddictMvcBinder(options);
var provider = new EmptyModelMetadataProvider();
var request = new OpenIdConnectRequest();
@@ -142,7 +182,9 @@ namespace OpenIddict.Mvc.Tests
public async Task BindModelAsync_ReturnsAmbientResponse()
{
// Arrange
- var binder = new OpenIddictModelBinder();
+ var options = Options.Create(new OpenIddictMvcOptions());
+
+ var binder = new OpenIddictMvcBinder(options);
var provider = new EmptyModelMetadataProvider();
var response = new OpenIdConnectResponse();
@@ -173,48 +215,5 @@ namespace OpenIddict.Mvc.Tests
Assert.Same(response, context.Result.Model);
Assert.True(context.ValidationState[response].SuppressValidation);
}
-
- [Theory]
- [InlineData(typeof(object))]
- [InlineData(typeof(IList))]
- [InlineData(typeof(int[]))]
- public void GetBinder_ReturnsNullForUnsupportedTypes(Type type)
- {
- // Arrange
- var provider = new OpenIddictModelBinder();
-
- var metadata = new Mock(ModelMetadataIdentity.ForType(type));
-
- var context = new Mock();
- context.Setup(mock => mock.Metadata)
- .Returns(metadata.Object);
-
- // Act
- var result = provider.GetBinder(context.Object);
-
- // Assert
- Assert.Null(result);
- }
-
- [Theory]
- [InlineData(typeof(OpenIdConnectRequest))]
- [InlineData(typeof(OpenIdConnectResponse))]
- public void GetBinder_ReturnsNonNullForSupportedTypes(Type type)
- {
- // Arrange
- var binder = new OpenIddictModelBinder();
-
- var metadata = new Mock(ModelMetadataIdentity.ForType(type));
-
- var context = new Mock();
- context.Setup(mock => mock.Metadata)
- .Returns(metadata.Object);
-
- // Act
- var result = binder.GetBinder(context.Object);
-
- // Assert
- Assert.Same(binder, result);
- }
}
}
diff --git a/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs b/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs
index ac35e7d6..abd27bae 100644
--- a/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs
+++ b/test/OpenIddict.Server.Tests/OpenIddictServerBuilderTests.cs
@@ -9,8 +9,6 @@ using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using AspNet.Security.OpenIdConnect.Primitives;
using Microsoft.AspNetCore.DataProtection;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
@@ -694,33 +692,15 @@ namespace OpenIddict.Server.Tests
Assert.True(options.Value.UseReferenceTokens);
}
- private static OpenIddictServerBuilder CreateBuilder(IServiceCollection services)
- => services.AddOpenIddict()
- .AddCore(options =>
- {
- options.SetDefaultApplicationEntity()
- .SetDefaultAuthorizationEntity()
- .SetDefaultScopeEntity()
- .SetDefaultTokenEntity();
- })
-
- .AddServer();
-
private static IServiceCollection CreateServices()
- {
- var services = new ServiceCollection();
- services.AddAuthentication();
- services.AddDistributedMemoryCache();
- services.AddLogging();
- services.AddSingleton();
+ => new ServiceCollection().AddOptions();
- return services;
- }
+ private static OpenIddictServerBuilder CreateBuilder(IServiceCollection services)
+ => new OpenIddictServerBuilder(services);
private static OpenIddictServerOptions GetOptions(IServiceCollection services)
{
var provider = services.BuildServiceProvider();
-
var options = provider.GetRequiredService>();
return options.Value;
}