Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Make types in Microsoft.AspNetCore.Mvc.Internal namespace internal #8646

Merged
merged 1 commit into from
Nov 8, 2018

Conversation

pranavkm
Copy link
Contributor

No description provided.

@pranavkm pranavkm force-pushed the prkrishn/no-internal branch from 2184955 to 1fa40b8 Compare October 25, 2018 23:57
@khellang
Copy link
Contributor

Noooo. Why?

@pranavkm pranavkm force-pushed the prkrishn/no-internal branch from 1fa40b8 to 8e61598 Compare October 25, 2018 23:57
@pranavkm pranavkm changed the title Make .Internal namespaces types to internal types Make types in Microsoft.AspNetCore.Mvc.Internal namespace internal Oct 25, 2018
IEnumerable<IControllerPropertyActivator> propertyActivators
#pragma warning restore PUB0001
)
IEnumerable<IControllerPropertyActivator> propertyActivators)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good 3.0 change 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there no PUB0001 warnings after this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least not in Mvc.Core

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is @pakrym analyzer on the repo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, that's unchanged

{
using Options = Options.Options;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm? Why here instead of the top of the file with other usings?

@@ -15,4 +15,8 @@
<PackageReference Include="Microsoft.Extensions.WebEncoders" Version="$(MicrosoftExtensionsWebEncodersPackageVersion)" />
</ItemGroup>

<ItemGroup>
<Folder Include="Properties\" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional?

@@ -26,19 +24,19 @@ public DefaultOrderTest(MvcTestFixture<BasicWebSite.Startup> fixture)
public HttpClient Client { get; }

[Theory]
[InlineData(typeof(IActionDescriptorProvider), typeof(ControllerActionDescriptorProvider), -1000)]
[InlineData(typeof(IActionDescriptorProvider), "Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerActionDescriptorProvider", -1000)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the team's thoughts on InternalsVisibleTo to test projects? Personally I don't have a problem with them, and would rather them over using string for type comparisons in tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JamesNK this case is a bit different, unit test projects see all the internals but functional tests do not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This specific test is kinda awful - it's a functional test, for what can be written as a unit test. Additionally, I'm not entirely sure what the benefit of this test is - it verifies if the Order property on these types are set - we rarely test those since they nearly never change: https://github.com/aspnet/Mvc/blob/release/2.2/test/WebSites/BasicWebSite/Controllers/OrderController.cs#L13-L36

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm all up for internals visible to for testing purposes, better IVT than having a public/pubternal API (If we are not willing to break it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm planning on removing these tests in a follow up.

@poke
Copy link
Contributor

poke commented Oct 26, 2018

I want to second @khellang here: Why is this being done? What’s the problem with public but messaged-as-internal types?

@@ -95,14 +94,14 @@ public void OnProvidersExecuted(ActionDescriptorProviderContext context)
}
}

protected internal IEnumerable<ControllerActionDescriptor> GetDescriptors()
internal IEnumerable<ControllerActionDescriptor> GetDescriptors()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Makes it very clear external subclasses are no longer supported. Same for later virtual removals in this PR.

@@ -26,19 +24,19 @@ public DefaultOrderTest(MvcTestFixture<BasicWebSite.Startup> fixture)
public HttpClient Client { get; }

[Theory]
[InlineData(typeof(IActionDescriptorProvider), typeof(ControllerActionDescriptorProvider), -1000)]
[InlineData(typeof(IActionDescriptorProvider), "Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerActionDescriptorProvider", -1000)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JamesNK this case is a bit different, unit test projects see all the internals but functional tests do not.

{
public class ActionConstraintCache
internal sealed class ActionConstraintCache
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding sealed probably doesn't hurt. But, it doesn't help much with internal types and is added randomly in this PR. Suggest reverting all of these additions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sort of did this to identify virtual methods that were implemented on previously pub internal types. Seems pretty harmless, but if you feel strongly about it I can remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If its just one find and replace, I would change it. That way in the future people will not wonder why they are internal sealed or think that this is an actual code pattern that we follow

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree w/ @javiercn

@@ -475,7 +474,7 @@ protected virtual ParameterModel CreateParameterModel(ParameterInfo parameterInf
return parameterModel;
}

private IList<SelectorModel> CreateSelectors(IList<object> attributes)
internal IList<SelectorModel> CreateSelectors(IList<object> attributes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh? Why is this changing?

@pranavkm pranavkm force-pushed the prkrishn/no-internal branch 3 times, most recently from f722a1e to 3871e95 Compare November 5, 2018 21:57
{
public class ActionConstraintCache
internal sealed class ActionConstraintCache
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sort of did this to identify virtual methods that were implemented on previously pub internal types. Seems pretty harmless, but if you feel strongly about it I can remove it.


namespace Microsoft.AspNetCore.Mvc.Controllers
{
public class ControllerFactoryProvider : IControllerFactoryProvider
internal class ControllerFactoryProvider : IControllerFactoryProvider
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit undecided on some types that previously exposed pub-internal types. On one hand,

  • we could make the pub-internal type public and that's less change.

  • On the other hand, things like IControllerPropertyActivator are an implementation detail and I'm not super sure if we it needs to be made public. Additionally, our guidance would be to use the interface contract IControllerFactoryProvider rather than the implementation type in user code.

Thoughts \ suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer we go "internal by default" and that we revisit internal/pub-ternal types 1 by 1 based on scenarios. This has caused us pain in the past (for example limiting our ability to do breaking changes) when we've added virtual methods to pub-ternal types without thinking about them and then having them be a limiting factor in next releases

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as we're left with nothing in ...Internal namespaces, we don't change anything truly public to internal, and public members exclusively use public types, I think we're fine. There's probably a few things on the margin that we should discuss case-by-case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And, in this case, internal makes sense

IEnumerable<IControllerPropertyActivator> propertyActivators
#pragma warning restore PUB0001
)
IEnumerable<IControllerPropertyActivator> propertyActivators)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least not in Mvc.Core


namespace Microsoft.AspNetCore.Mvc.Controllers
{
/// <summary>
/// <see cref="IControllerActivator"/> that uses type activation to create controllers.
/// </summary>
public class DefaultControllerActivator : IControllerActivator
internal sealed class DefaultControllerActivator : IControllerActivator
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as DefaultControllerFactory. ITypeActivatorCache is pub-internal in 2.x and feels like infrastructure that doesn't need to be made public.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should think about how users extend the framework or what story do we want to tell them. We need to strike a balance between overriding a method or telling them to provide their own entire implementation. (Specially for classes with a lot of dependencies or complex implementations). If people end up copying the code of the internal type they automatically opt-out of patches, etc for that area of the code base, and that's not a good story. In the past we had a lot of problems in traditional web api because of these type of things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't make any truly public class internal in this sweep. Err on the side of compatibility. And, if that means ITypeActivatorCache must be public, that's 🆗

{
/// <summary>
/// A media type with its associated quality.
/// </summary>
public readonly struct MediaTypeSegmentWithQuality
internal readonly struct MediaTypeSegmentWithQuality
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was an effort to do this by @jkotalik but I'm not sure where it ended. There were some differences in behavior I believe, as we are more "lax" parsing things in order to maintain compatibility with bad behaving clients, all this done for historical reasons where the knowledge has been lost in time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should consider deprecating the MediaType class in 2.2 and replacing it with MediaTypeHeaderValue (MTHV). I was working on making MediaType a wrapper class around MTHV, but there were a good number of functional differences and the effort was abandoned.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2.2's done, so deprecating it isn't an option. But we could make an announcement and deprecate the type in 3.0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then don't we need to wait until 4.x to remove it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably completely replace it as it’s a major version and I don’t think this type will have a lot of external usage. As long as we preserve the same set of allowed inputs it should be ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Eilon is this something we can consider making Obsolete in 2.2?

@@ -46,9 +45,7 @@ public class FormValueProvider : BindingSourceValueProvider, IEnumerableValuePro

public CultureInfo Culture => _culture;

#pragma warning disable PUB0001 // Pubternal type in public API
protected PrefixContainer PrefixContainer
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PrefixContainer seems like a fairly useful \ well-designed type and I was planning on making it public as part of this change. Concerns?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None here

@@ -101,9 +100,7 @@ public abstract class ObjectModelValidator : IObjectModelValidator
public abstract ValidationVisitor GetValidationVisitor(
ActionContext actionContext,
IModelValidatorProvider validatorProvider,
#pragma warning disable PUB0001 // Pubternal type in public API
ValidatorCache validatorCache,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API is used by FluentValidation and I didn't want to do too much refactoring here to avoid churn in their library. ValidatorCache is made public in this change, but it's a very infrastructural type that libraries shouldn't need to interact with

@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents
/// <see cref="ViewComponentContext"/> to a public property of a view component marked
/// with <see cref="ViewComponentContextAttribute"/>.
/// </remarks>
public class DefaultViewComponentActivator : IViewComponentActivator
internal sealed class DefaultViewComponentActivator : IViewComponentActivator
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has the same issue as other public types that exposed pub-internal types. I've listed individual types that changed as a result since it warrants looking at them on a case by case basis

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I prefer we don't make public types internal, this change seems fine

@@ -14,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
/// <summary>
/// Default implementation of <see cref="ValidationHtmlAttributeProvider"/>.
/// </summary>
public class DefaultValidationHtmlAttributeProvider : ValidationHtmlAttributeProvider
internal sealed class DefaultValidationHtmlAttributeProvider : ValidationHtmlAttributeProvider
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest this should be public since it's difficult to extend the validation system without it. If that means we expose ClientValidatorCache or a new IClientValidatorCache interface, fine.

@@ -26,19 +24,19 @@ public DefaultOrderTest(MvcTestFixture<BasicWebSite.Startup> fixture)
public HttpClient Client { get; }

[Theory]
[InlineData(typeof(IActionDescriptorProvider), typeof(ControllerActionDescriptorProvider), -1000)]
[InlineData(typeof(IActionDescriptorProvider), "Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerActionDescriptorProvider", -1000)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This specific test is kinda awful - it's a functional test, for what can be written as a unit test. Additionally, I'm not entirely sure what the benefit of this test is - it verifies if the Order property on these types are set - we rarely test those since they nearly never change: https://github.com/aspnet/Mvc/blob/release/2.2/test/WebSites/BasicWebSite/Controllers/OrderController.cs#L13-L36

_propertyActivators = propertyActivators.ToArray();
}

/// <summary>
/// The <see cref="IControllerActivator"/> used to create a controller.
/// </summary>
protected IControllerActivator ControllerActivator => _controllerActivator;
private IControllerActivator ControllerActivator { get; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to move these things into props and make them explicitly private? I would have left the private readonly var instead. We don't do private properties anywhere AFAIK

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

{
public class ActionConstraintCache
internal sealed class ActionConstraintCache
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree w/ @javiercn


namespace Microsoft.AspNetCore.Mvc.Controllers
{
public class ControllerFactoryProvider : IControllerFactoryProvider
internal class ControllerFactoryProvider : IControllerFactoryProvider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as we're left with nothing in ...Internal namespaces, we don't change anything truly public to internal, and public members exclusively use public types, I think we're fine. There's probably a few things on the margin that we should discuss case-by-case.


namespace Microsoft.AspNetCore.Mvc.Controllers
{
public class ControllerFactoryProvider : IControllerFactoryProvider
internal class ControllerFactoryProvider : IControllerFactoryProvider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And, in this case, internal makes sense


namespace Microsoft.AspNetCore.Mvc.Controllers
{
/// <summary>
/// <see cref="IControllerActivator"/> that uses type activation to create controllers.
/// </summary>
public class DefaultControllerActivator : IControllerActivator
internal sealed class DefaultControllerActivator : IControllerActivator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't make any truly public class internal in this sweep. Err on the side of compatibility. And, if that means ITypeActivatorCache must be public, that's 🆗


namespace Microsoft.AspNetCore.Mvc.Controllers
{
/// <summary>
/// Default implementation for <see cref="IControllerFactory"/>.
/// </summary>
public class DefaultControllerFactory : IControllerFactory
internal sealed class DefaultControllerFactory : IControllerFactory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like another change in the wrong direction. Again, err on the side of compatibility

@@ -21,7 +21,7 @@

namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class PageActionInvoker : ResourceInvoker, IActionInvoker
internal class PageActionInvoker : ResourceInvoker, IActionInvoker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, empty out the .Internal namespaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Focusing on Mvc.Core for now. Will do this in follow up

@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents
/// <see cref="ViewComponentContext"/> to a public property of a view component marked
/// with <see cref="ViewComponentContextAttribute"/>.
/// </remarks>
public class DefaultViewComponentActivator : IViewComponentActivator
internal sealed class DefaultViewComponentActivator : IViewComponentActivator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I prefer we don't make public types internal, this change seems fine

@@ -14,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
/// <summary>
/// Default implementation of <see cref="ValidationHtmlAttributeProvider"/>.
/// </summary>
public class DefaultValidationHtmlAttributeProvider : ValidationHtmlAttributeProvider
internal sealed class DefaultValidationHtmlAttributeProvider : ValidationHtmlAttributeProvider
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest this should be public since it's difficult to extend the validation system without it. If that means we expose ClientValidatorCache or a new IClientValidatorCache interface, fine.

@@ -19,7 +19,7 @@ public int GetServiceOrder(string serviceType, string actualType)
var services = (IEnumerable<object>)HttpContext?.RequestServices.GetService(queryType);
foreach (var service in services)
{
if (actualType != null && service.GetType().AssemblyQualifiedName == actualType)
if (actualType != null && service.GetType().FullName == actualType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated bug?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to pass the full name with version along. Anyway, this test should go away soon.

@@ -29,7 +29,7 @@ public abstract class CommonResourceInvokerTest
return CreateInvoker(new IFilterMetadata[] { filter }, exception, result, valueProviderFactories);
}

protected abstract ResourceInvoker CreateInvoker(
protected abstract IActionInvoker CreateInvoker(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changing, is ResourceInvoker internal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@pranavkm pranavkm force-pushed the prkrishn/no-internal branch 6 times, most recently from 8cb0c6e to 4eea841 Compare November 6, 2018 23:23
@pranavkm
Copy link
Contributor Author

pranavkm commented Nov 6, 2018

🆙 📅

@pranavkm
Copy link
Contributor Author

pranavkm commented Nov 8, 2018

Plan on merging this today. Let me know if there's any additional feedback.

Copy link
Contributor

@dougbu dougbu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. But, I have a few smaller comments and questions…

@@ -3,7 +3,7 @@

using Microsoft.Extensions.Primitives;

namespace Microsoft.AspNetCore.Mvc.Formatters.Internal
namespace Microsoft.AspNetCore.Mvc.Formatters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confirm: For now at least, we're making this truly public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Tracking this via #8694. I'll set up a design review for this once I'm done with the remainder of assemblies.

@@ -34,7 +34,7 @@ public NonDisposableStream(Stream innerStream)
/// <summary>
/// The inner stream this object delegates to.
/// </summary>
protected Stream InnerStream => _innerStream;
private Stream InnerStream => _innerStream;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor but this property no longer looks useful. Just use _innerStream.


namespace Microsoft.AspNetCore.Mvc.ModelBinding.Internal
namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
{
public class ValidationStack
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What drives this one becoming truly public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was exposed as a protected property on ValidationVisitor. My guess is that we should be safe to make the property private and the type internal, but let's sort this as part of #8694

using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this using? Seems to make the Options.Create(...) calls messier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the type is is Microsoft.Extension.DependencyInjection, doing Options. inside refers to the namespace and not the type. Kinda have to namespace qualify Options

@pranavkm pranavkm force-pushed the prkrishn/no-internal branch from 4eea841 to 7cf914f Compare November 8, 2018 21:40
@pranavkm pranavkm merged commit 8d66f10 into master Nov 8, 2018
@pranavkm pranavkm deleted the prkrishn/no-internal branch November 8, 2018 22:00
@@ -36,7 +36,7 @@ public interface IActionSelector
/// <param name="context">The <see cref="RouteContext"/> associated with the current request.</param>
/// <param name="candidates">The set of <see cref="ActionDescriptor"/> candidates.</param>
/// <returns>The best <see cref="ActionDescriptor"/> candidate for the current request or <c>null</c>.</returns>
/// <exception cref="Internal.AmbiguousActionException">
/// <exception cref="AmbiguousActionException">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AmbiguousActionException just got made internal but this interface is public.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants