[MVC] Remove obsolete APIs
- Removed ViewsFeatureProvider - Removed PageArgumentBinder and its internal implementation DefaultPageArgumentBinder. - Removed corresponding test classes/methods for all the above. - Reacted to class/member changes in dependencies. #7326
This commit is contained in:
parent
597c8434d5
commit
dfddc4e8ff
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
|||
|
||||
foreach (var item in provider.CompiledItems)
|
||||
{
|
||||
var descriptor = new CompiledViewDescriptor(item, attribute: null);
|
||||
var descriptor = new CompiledViewDescriptor(item);
|
||||
feature.ViewDescriptors.Add(descriptor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IApplicationFeatureProvider{TFeature}"/> for <see cref="ViewsFeature"/>.
|
||||
/// </summary>
|
||||
[Obsolete("This type is obsolete and will be removed in a future version. See " + nameof(IRazorCompiledItemProvider) + " for alternatives.")]
|
||||
public class ViewsFeatureProvider : IApplicationFeatureProvider<ViewsFeature>
|
||||
{
|
||||
public static readonly string PrecompiledViewsAssemblySuffix = ".PrecompiledViews";
|
||||
|
||||
/// <inheritdoc />
|
||||
public void PopulateFeature(IEnumerable<ApplicationPart> parts, ViewsFeature feature)
|
||||
{
|
||||
foreach (var assemblyPart in parts.OfType<AssemblyPart>())
|
||||
{
|
||||
var viewAttributes = GetViewAttributes(assemblyPart)
|
||||
.Select(attribute => (Attribute: attribute, RelativePath: ViewPath.NormalizePath(attribute.Path)));
|
||||
|
||||
var duplicates = viewAttributes.GroupBy(a => a.RelativePath, StringComparer.OrdinalIgnoreCase)
|
||||
.FirstOrDefault(g => g.Count() > 1);
|
||||
|
||||
if (duplicates != null)
|
||||
{
|
||||
// Ensure parts do not specify views with differing cases. This is not supported
|
||||
// at runtime and we should flag at as such for precompiled views.
|
||||
var viewsDifferingInCase = string.Join(Environment.NewLine, duplicates.Select(d => d.RelativePath));
|
||||
|
||||
var message = string.Join(
|
||||
Environment.NewLine,
|
||||
Resources.RazorViewCompiler_ViewPathsDifferOnlyInCase,
|
||||
viewsDifferingInCase);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
foreach (var (attribute, relativePath) in viewAttributes)
|
||||
{
|
||||
var viewDescriptor = new CompiledViewDescriptor
|
||||
{
|
||||
ExpirationTokens = Array.Empty<IChangeToken>(),
|
||||
RelativePath = relativePath,
|
||||
ViewAttribute = attribute,
|
||||
};
|
||||
|
||||
feature.ViewDescriptors.Add(viewDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sequence of <see cref="RazorViewAttribute"/> instances associated with the specified <paramref name="assemblyPart"/>.
|
||||
/// </summary>
|
||||
/// <param name="assemblyPart">The <see cref="AssemblyPart"/>.</param>
|
||||
/// <returns>The sequence of <see cref="RazorViewAttribute"/> instances.</returns>
|
||||
protected virtual IEnumerable<RazorViewAttribute> GetViewAttributes(AssemblyPart assemblyPart)
|
||||
{
|
||||
if (assemblyPart == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(assemblyPart));
|
||||
}
|
||||
|
||||
var featureAssembly = GetFeatureAssembly(assemblyPart);
|
||||
if (featureAssembly != null)
|
||||
{
|
||||
return featureAssembly.GetCustomAttributes<RazorViewAttribute>();
|
||||
}
|
||||
|
||||
return Enumerable.Empty<RazorViewAttribute>();
|
||||
}
|
||||
|
||||
private static Assembly GetFeatureAssembly(AssemblyPart assemblyPart)
|
||||
{
|
||||
if (assemblyPart.Assembly.IsDynamic || string.IsNullOrEmpty((string)assemblyPart.Assembly.Location))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var precompiledAssemblyFileName = assemblyPart.Assembly.GetName().Name
|
||||
+ PrecompiledViewsAssemblySuffix
|
||||
+ ".dll";
|
||||
|
||||
var precompiledAssemblyFilePath = Path.Combine(
|
||||
Path.GetDirectoryName(assemblyPart.Assembly.Location),
|
||||
precompiledAssemblyFileName);
|
||||
|
||||
if (File.Exists(precompiledAssemblyFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
return Assembly.LoadFile(precompiledAssemblyFilePath);
|
||||
}
|
||||
catch (FileLoadException)
|
||||
{
|
||||
// Don't throw if assembly cannot be loaded. This can happen if the file is not a managed assembly.
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,13 +72,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
builder.PartManager.FeatureProviders.Add(new RazorCompiledItemFeatureProvider());
|
||||
}
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (!builder.PartManager.FeatureProviders.OfType<ViewsFeatureProvider>().Any())
|
||||
{
|
||||
builder.PartManager.FeatureProviders.Add(new ViewsFeatureProvider());
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -114,11 +114,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddSingleton<IPageLoader, DefaultPageLoader>();
|
||||
services.TryAddSingleton<IPageHandlerMethodSelector, DefaultPageHandlerMethodSelector>();
|
||||
|
||||
// Page model binding
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
services.TryAddSingleton<PageArgumentBinder, DefaultPageArgumentBinder>();
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
// Action executors
|
||||
services.TryAddSingleton<PageResultExecutor>();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
internal class DefaultPageArgumentBinder : PageArgumentBinder
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
{
|
||||
private readonly ParameterBinder _parameterBinder;
|
||||
|
||||
public DefaultPageArgumentBinder(ParameterBinder binder)
|
||||
{
|
||||
_parameterBinder = binder;
|
||||
}
|
||||
|
||||
protected override async Task<ModelBindingResult> BindAsync(PageContext pageContext, object value, string name, Type type)
|
||||
{
|
||||
var valueProvider = await GetCompositeValueProvider(pageContext);
|
||||
var parameterDescriptor = new ParameterDescriptor
|
||||
{
|
||||
BindingInfo = null,
|
||||
Name = name,
|
||||
ParameterType = type,
|
||||
};
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return await _parameterBinder.BindModelAsync(pageContext, valueProvider, parameterDescriptor, value);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
private static async Task<CompositeValueProvider> GetCompositeValueProvider(PageContext pageContext)
|
||||
{
|
||||
var factories = pageContext.ValueProviderFactories;
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(pageContext);
|
||||
for (var i = 0; i < factories.Count; i++)
|
||||
{
|
||||
var factory = factories[i];
|
||||
await factory.CreateValueProviderAsync(valueProviderFactoryContext);
|
||||
}
|
||||
|
||||
return new CompositeValueProvider(valueProviderFactoryContext.ValueProviders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||
{
|
||||
[Obsolete("This type is obsolete and will be removed in a future version.")]
|
||||
public abstract class PageArgumentBinder
|
||||
{
|
||||
public async Task<object> BindModelAsync(PageContext context, Type type, object @default, string name)
|
||||
{
|
||||
var result = await BindAsync(context, null, name, type);
|
||||
return result.IsModelSet ? result.Model : @default;
|
||||
}
|
||||
|
||||
public Task<TModel> BindModelAsync<TModel>(PageContext context, string name)
|
||||
{
|
||||
return BindModelAsync(context, default(TModel), name);
|
||||
}
|
||||
|
||||
public async Task<TModel> BindModelAsync<TModel>(PageContext context, TModel @default, string name)
|
||||
{
|
||||
var result = await BindAsync(context, null, name, typeof(TModel));
|
||||
return result.IsModelSet ? (TModel)result.Model : @default;
|
||||
}
|
||||
|
||||
public async Task<bool> TryUpdateModelAsync<TModel>(PageContext context, TModel value)
|
||||
{
|
||||
var result = await BindAsync(context, value, string.Empty, typeof(TModel));
|
||||
return result.IsModelSet && context.ModelState.IsValid;
|
||||
}
|
||||
|
||||
public async Task<bool> TryUpdateModelAsync<TModel>(PageContext context, TModel value, string name)
|
||||
{
|
||||
var result = await BindAsync(context, value, name, typeof(TModel));
|
||||
return result.IsModelSet && context.ModelState.IsValid;
|
||||
}
|
||||
|
||||
protected abstract Task<ModelBindingResult> BindAsync(PageContext context, object value, string name, Type type);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,17 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
private readonly RazorPageBase _page;
|
||||
private readonly Type _modelType;
|
||||
|
||||
[Obsolete("This constructor is obsolete and will be removed in a future version.")]
|
||||
public RazorPageAdapter(RazorPageBase page)
|
||||
{
|
||||
if (page == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(page));
|
||||
}
|
||||
|
||||
_page = page;
|
||||
}
|
||||
|
||||
public RazorPageAdapter(RazorPageBase page, Type modelType)
|
||||
{
|
||||
_page = page ?? throw new ArgumentNullException(nameof(page));
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFeature_PopulatesRazorViewAttributeFromTypeAssembly()
|
||||
public void PopulateFeature_PopulatesRazorCompiledItemsFromTypeAssembly()
|
||||
{
|
||||
// Arrange
|
||||
var item1 = Mock.Of<RazorCompiledItem>(i => i.Identifier == "Item1" && i.Type == typeof(TestView));
|
||||
|
|
|
|||
|
|
@ -1,197 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
public class ViewsFeatureProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void PopulateFeature_ReturnsEmptySequenceIfNoAssemblyPartHasViewAssembly()
|
||||
{
|
||||
// Arrange
|
||||
var applicationPartManager = new ApplicationPartManager();
|
||||
applicationPartManager.ApplicationParts.Add(
|
||||
new AssemblyPart(typeof(ViewsFeatureProviderTest).GetTypeInfo().Assembly));
|
||||
applicationPartManager.FeatureProviders.Add(new ViewsFeatureProvider());
|
||||
var feature = new ViewsFeature();
|
||||
|
||||
// Act
|
||||
applicationPartManager.PopulateFeature(feature);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(feature.ViewDescriptors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFeature_ReturnsViewsFromAllAvailableApplicationParts()
|
||||
{
|
||||
// Arrange
|
||||
var part1 = new AssemblyPart(typeof(object).GetTypeInfo().Assembly);
|
||||
var part2 = new AssemblyPart(GetType().GetTypeInfo().Assembly);
|
||||
var featureProvider = new TestableViewsFeatureProvider(new Dictionary<AssemblyPart, IEnumerable<RazorViewAttribute>>
|
||||
{
|
||||
{
|
||||
part1,
|
||||
new[]
|
||||
{
|
||||
new RazorViewAttribute("/Views/test/Index.cshtml", typeof(object)),
|
||||
}
|
||||
},
|
||||
{
|
||||
part2,
|
||||
new[]
|
||||
{
|
||||
new RazorViewAttribute("/Areas/Admin/Views/Index.cshtml", typeof(string)),
|
||||
new RazorViewAttribute("/Areas/Admin/Views/About.cshtml", typeof(int)),
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var applicationPartManager = new ApplicationPartManager();
|
||||
applicationPartManager.ApplicationParts.Add(part1);
|
||||
applicationPartManager.ApplicationParts.Add(part2);
|
||||
applicationPartManager.FeatureProviders.Add(featureProvider);
|
||||
var feature = new ViewsFeature();
|
||||
|
||||
// Act
|
||||
applicationPartManager.PopulateFeature(feature);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(feature.ViewDescriptors.OrderBy(f => f.RelativePath, StringComparer.Ordinal),
|
||||
view =>
|
||||
{
|
||||
Assert.Equal("/Areas/Admin/Views/About.cshtml", view.RelativePath);
|
||||
Assert.Equal(typeof(int), view.ViewAttribute.ViewType);
|
||||
},
|
||||
view =>
|
||||
{
|
||||
Assert.Equal("/Areas/Admin/Views/Index.cshtml", view.RelativePath);
|
||||
Assert.Equal(typeof(string), view.ViewAttribute.ViewType);
|
||||
},
|
||||
view =>
|
||||
{
|
||||
Assert.Equal("/Views/test/Index.cshtml", view.RelativePath);
|
||||
Assert.Equal(typeof(object), view.ViewAttribute.ViewType);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFeature_ThrowsIfSingleAssemblyContainsMultipleAttributesWithTheSamePath()
|
||||
{
|
||||
// Arrange
|
||||
var path1 = "/Views/test/Index.cshtml";
|
||||
var path2 = "/views/test/index.cshtml";
|
||||
var expected = string.Join(
|
||||
Environment.NewLine,
|
||||
"The following precompiled view paths differ only in case, which is not supported:",
|
||||
path1,
|
||||
path2);
|
||||
var part = new AssemblyPart(typeof(object).GetTypeInfo().Assembly);
|
||||
var featureProvider = new TestableViewsFeatureProvider(new Dictionary<AssemblyPart, IEnumerable<RazorViewAttribute>>
|
||||
{
|
||||
{
|
||||
part,
|
||||
new[]
|
||||
{
|
||||
new RazorViewAttribute(path1, typeof(object)),
|
||||
new RazorViewAttribute(path2, typeof(object)),
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var applicationPartManager = new ApplicationPartManager();
|
||||
applicationPartManager.ApplicationParts.Add(part);
|
||||
applicationPartManager.FeatureProviders.Add(featureProvider);
|
||||
var feature = new ViewsFeature();
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => applicationPartManager.PopulateFeature(feature));
|
||||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFeature_ReturnsEmptySequenceIfNoDynamicAssemblyPartHasViewAssembly()
|
||||
{
|
||||
// Arrange
|
||||
var name = new AssemblyName($"DynamicAssembly-{Guid.NewGuid()}");
|
||||
var assembly = AssemblyBuilder.DefineDynamicAssembly(name,
|
||||
AssemblyBuilderAccess.RunAndCollect);
|
||||
|
||||
var applicationPartManager = new ApplicationPartManager();
|
||||
applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
|
||||
applicationPartManager.FeatureProviders.Add(new ViewsFeatureProvider());
|
||||
var feature = new ViewsFeature();
|
||||
|
||||
// Act
|
||||
applicationPartManager.PopulateFeature(feature);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(feature.ViewDescriptors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFeature_DoesNotFail_IfAssemblyHasEmptyLocation()
|
||||
{
|
||||
// Arrange
|
||||
var assembly = new AssemblyWithEmptyLocation();
|
||||
var applicationPartManager = new ApplicationPartManager();
|
||||
applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
|
||||
applicationPartManager.FeatureProviders.Add(new ViewsFeatureProvider());
|
||||
var feature = new ViewsFeature();
|
||||
|
||||
// Act
|
||||
applicationPartManager.PopulateFeature(feature);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(feature.ViewDescriptors);
|
||||
}
|
||||
|
||||
private class TestableViewsFeatureProvider : ViewsFeatureProvider
|
||||
{
|
||||
private readonly Dictionary<AssemblyPart, IEnumerable<RazorViewAttribute>> _attributeLookup;
|
||||
|
||||
public TestableViewsFeatureProvider(Dictionary<AssemblyPart, IEnumerable<RazorViewAttribute>> attributeLookup)
|
||||
{
|
||||
_attributeLookup = attributeLookup;
|
||||
}
|
||||
|
||||
protected override IEnumerable<RazorViewAttribute> GetViewAttributes(AssemblyPart assemblyPart)
|
||||
{
|
||||
return _attributeLookup[assemblyPart];
|
||||
}
|
||||
}
|
||||
|
||||
private class AssemblyWithEmptyLocation : Assembly
|
||||
{
|
||||
public override string Location => string.Empty;
|
||||
|
||||
public override string FullName => typeof(ViewsFeatureProviderTest).GetTypeInfo().Assembly.FullName;
|
||||
|
||||
public override IEnumerable<TypeInfo> DefinedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Module> Modules
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
|
@ -209,10 +209,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
feature => Assert.IsType<ControllerFeatureProvider>(feature),
|
||||
feature => Assert.IsType<ViewComponentFeatureProvider>(feature),
|
||||
feature => Assert.IsType<TagHelperFeatureProvider>(feature),
|
||||
feature => Assert.IsType<RazorCompiledItemFeatureProvider>(feature),
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
feature => Assert.IsType<ViewsFeatureProvider>(feature));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
feature => Assert.IsType<RazorCompiledItemFeatureProvider>(feature));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Reference in New Issue