Use dependency context from all application parts when compiling views
Fixes #4498
This commit is contained in:
parent
27565c4e8d
commit
ab76f743f4
|
|
@ -4,13 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.Extensions.DependencyModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An <see cref="ApplicationPart"/> backed by an <see cref="Assembly"/>.
|
/// An <see cref="ApplicationPart"/> backed by an <see cref="Assembly"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider
|
public class AssemblyPart : ApplicationPart, IApplicationPartTypeProvider, ICompilationLibrariesProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initalizes a new <see cref="AssemblyPart"/> instance.
|
/// Initalizes a new <see cref="AssemblyPart"/> instance.
|
||||||
|
|
@ -38,5 +39,17 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes;
|
public IEnumerable<TypeInfo> Types => Assembly.DefinedTypes;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IReadOnlyList<CompilationLibrary> GetCompilationLibraries()
|
||||||
|
{
|
||||||
|
var dependencyContext = DependencyContext.Load(Assembly);
|
||||||
|
if (dependencyContext != null)
|
||||||
|
{
|
||||||
|
return dependencyContext.CompileLibraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CompilationLibrary[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.DependencyModel;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.ApplicationParts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exposes <see cref="CompilationLibrary"/> instances from an <see cref="ApplicationPart"/>.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICompilationLibrariesProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sequence of <see cref="CompilationLibrary"/> instances.
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyList<CompilationLibrary> GetCompilationLibraries();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the list of <see cref="MetadataReference"/> used in Razor compilation.
|
||||||
|
/// </summary>
|
||||||
|
public class MetadataReferenceFeature
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="MetadataReference"/> instances.
|
||||||
|
/// </summary>
|
||||||
|
public IList<MetadataReference> MetadataReferences { get; } = new List<MetadataReference>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
// 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.PortableExecutable;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.Extensions.DependencyModel;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="IApplicationFeatureProvider{TFeature}"/> for <see cref="MetadataReferenceFeature"/> that
|
||||||
|
/// uses <see cref="DependencyContext"/> for registered <see cref="AssemblyPart"/> instances to create
|
||||||
|
/// <see cref="MetadataReference"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class MetadataReferenceFeatureProvider : IApplicationFeatureProvider<MetadataReferenceFeature>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void PopulateFeature(IEnumerable<ApplicationPart> parts, MetadataReferenceFeature feature)
|
||||||
|
{
|
||||||
|
if (parts == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(parts));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feature == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(feature));
|
||||||
|
}
|
||||||
|
|
||||||
|
var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var providerPart in parts.OfType<ICompilationLibrariesProvider>())
|
||||||
|
{
|
||||||
|
var compileLibraries = providerPart.GetCompilationLibraries();
|
||||||
|
|
||||||
|
for (var i = 0; i < compileLibraries.Count; i++)
|
||||||
|
{
|
||||||
|
var library = compileLibraries[i];
|
||||||
|
var referencePaths = library.ResolveReferencePaths();
|
||||||
|
foreach (var path in referencePaths)
|
||||||
|
{
|
||||||
|
if (libraryPaths.Add(path))
|
||||||
|
{
|
||||||
|
var metadataReference = CreateMetadataReference(path);
|
||||||
|
feature.MetadataReferences.Add(metadataReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MetadataReference CreateMetadataReference(string path)
|
||||||
|
{
|
||||||
|
using (var stream = File.OpenRead(path))
|
||||||
|
{
|
||||||
|
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
|
||||||
|
var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
|
||||||
|
|
||||||
|
return assemblyMetadata.GetReference(filePath: path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -67,6 +67,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||||
{
|
{
|
||||||
builder.PartManager.FeatureProviders.Add(new TagHelperFeatureProvider());
|
builder.PartManager.FeatureProviders.Add(new TagHelperFeatureProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!builder.PartManager.FeatureProviders.OfType<MetadataReferenceFeatureProvider>().Any())
|
||||||
|
{
|
||||||
|
builder.PartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,15 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.PortableExecutable;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Diagnostics;
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.Emit;
|
using Microsoft.CodeAnalysis.Emit;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using Microsoft.Extensions.DependencyModel;
|
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -29,7 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DefaultRoslynCompilationService : ICompilationService
|
public class DefaultRoslynCompilationService : ICompilationService
|
||||||
{
|
{
|
||||||
private readonly IHostingEnvironment _hostingEnvironment;
|
private readonly ApplicationPartManager _partManager;
|
||||||
private readonly IFileProvider _fileProvider;
|
private readonly IFileProvider _fileProvider;
|
||||||
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
private readonly Action<RoslynCompilationContext> _compilationCallback;
|
||||||
private readonly CSharpParseOptions _parseOptions;
|
private readonly CSharpParseOptions _parseOptions;
|
||||||
|
|
@ -37,22 +35,22 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private object _applicationReferencesLock = new object();
|
private object _applicationReferencesLock = new object();
|
||||||
private bool _applicationReferencesInitialized;
|
private bool _applicationReferencesInitialized;
|
||||||
private List<MetadataReference> _applicationReferences;
|
private IList<MetadataReference> _applicationReferences;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
|
/// Initalizes a new instance of the <see cref="DefaultRoslynCompilationService"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="environment">The <see cref="IHostingEnvironment"/>.</param>
|
/// <param name="partManager">The <see cref="ApplicationPartManager"/>.</param>
|
||||||
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
/// <param name="optionsAccessor">Accessor to <see cref="RazorViewEngineOptions"/>.</param>
|
||||||
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
/// <param name="fileProviderAccessor">The <see cref="IRazorViewEngineFileProviderAccessor"/>.</param>
|
||||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||||
public DefaultRoslynCompilationService(
|
public DefaultRoslynCompilationService(
|
||||||
IHostingEnvironment environment,
|
ApplicationPartManager partManager,
|
||||||
IOptions<RazorViewEngineOptions> optionsAccessor,
|
IOptions<RazorViewEngineOptions> optionsAccessor,
|
||||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
|
IRazorViewEngineFileProviderAccessor fileProviderAccessor,
|
||||||
ILoggerFactory loggerFactory)
|
ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
_hostingEnvironment = environment;
|
_partManager = partManager;
|
||||||
_fileProvider = fileProviderAccessor.FileProvider;
|
_fileProvider = fileProviderAccessor.FileProvider;
|
||||||
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
_compilationCallback = optionsAccessor.Value.CompilationCallback;
|
||||||
_parseOptions = optionsAccessor.Value.ParseOptions;
|
_parseOptions = optionsAccessor.Value.ParseOptions;
|
||||||
|
|
@ -60,7 +58,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
_logger = loggerFactory.CreateLogger<DefaultRoslynCompilationService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MetadataReference> ApplicationReferences
|
private IList<MetadataReference> ApplicationReferences
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -152,19 +150,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the <see cref="DependencyContext"/>.
|
/// Gets the sequence of <see cref="MetadataReference"/> instances used for compilation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hostingEnvironment">The <see cref="IHostingEnvironment"/>.</param>
|
/// <returns>The <see cref="MetadataReference"/> instances.</returns>
|
||||||
/// <returns>The <see cref="DependencyContext"/>.</returns>
|
protected virtual IList<MetadataReference> GetApplicationReferences()
|
||||||
protected virtual DependencyContext GetDependencyContext(IHostingEnvironment hostingEnvironment)
|
|
||||||
{
|
{
|
||||||
if (hostingEnvironment.ApplicationName != null)
|
var feature = new MetadataReferenceFeature();
|
||||||
{
|
_partManager.PopulateFeature(feature);
|
||||||
var applicationAssembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
|
return feature.MetadataReferences;
|
||||||
return DependencyContext.Load(applicationAssembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Assembly LoadStream(MemoryStream assemblyStream, MemoryStream pdbStream)
|
private Assembly LoadStream(MemoryStream assemblyStream, MemoryStream pdbStream)
|
||||||
|
|
@ -240,53 +233,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
return diagnostic.Location.GetMappedLineSpan().Path;
|
return diagnostic.Location.GetMappedLineSpan().Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MetadataReference> GetApplicationReferences()
|
|
||||||
{
|
|
||||||
var metadataReferences = new List<MetadataReference>();
|
|
||||||
var dependencyContext = GetDependencyContext(_hostingEnvironment);
|
|
||||||
if (dependencyContext == null)
|
|
||||||
{
|
|
||||||
// Avoid null ref if the entry point does not have DependencyContext specified.
|
|
||||||
return metadataReferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
var libraryPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
for (var i = 0; i < dependencyContext.CompileLibraries.Count; i++)
|
|
||||||
{
|
|
||||||
var library = dependencyContext.CompileLibraries[i];
|
|
||||||
IEnumerable<string> referencePaths;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
referencePaths = library.ResolveReferencePaths();
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var path in referencePaths)
|
|
||||||
{
|
|
||||||
if (libraryPaths.Add(path))
|
|
||||||
{
|
|
||||||
metadataReferences.Add(CreateMetadataFileReference(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return metadataReferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MetadataReference CreateMetadataFileReference(string path)
|
|
||||||
{
|
|
||||||
using (var stream = File.OpenRead(path))
|
|
||||||
{
|
|
||||||
var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
|
|
||||||
var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
|
|
||||||
|
|
||||||
return assemblyMetadata.GetReference(filePath: path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsError(Diagnostic diagnostic)
|
private static bool IsError(Diagnostic diagnostic)
|
||||||
{
|
{
|
||||||
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
|
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
// 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.Reflection;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Razor.Compilation
|
||||||
|
{
|
||||||
|
public class MetadataReferenceFeatureProviderTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void PopulateFeature_ReturnsEmptyList_IfNoAssemblyPartsAreRegistered()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var applicationPartManager = new ApplicationPartManager();
|
||||||
|
applicationPartManager.ApplicationParts.Add(Mock.Of<ApplicationPart>());
|
||||||
|
applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
|
||||||
|
var feature = new MetadataReferenceFeature();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
applicationPartManager.PopulateFeature(feature);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(feature.MetadataReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PopulateFeature_ReturnsEmptySequence_IfAssemblyDoesNotPreserveCompilationContext()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var applicationPartManager = new ApplicationPartManager();
|
||||||
|
var assemblyPart = new AssemblyPart(typeof(MetadataReferenceFeatureProvider).GetTypeInfo().Assembly);
|
||||||
|
applicationPartManager.ApplicationParts.Add(assemblyPart);
|
||||||
|
applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
|
||||||
|
var feature = new MetadataReferenceFeature();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
applicationPartManager.PopulateFeature(feature);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(feature.MetadataReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PopulateFeature_AddsMetadataReferenceForAssemblyPartsWithDependencyContext()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var applicationPartManager = new ApplicationPartManager();
|
||||||
|
var currentAssembly = GetType().GetTypeInfo().Assembly;
|
||||||
|
var assemblyPart1 = new AssemblyPart(currentAssembly);
|
||||||
|
applicationPartManager.ApplicationParts.Add(assemblyPart1);
|
||||||
|
var assemblyPart2 = new AssemblyPart(typeof(MetadataReferenceFeatureProvider).GetTypeInfo().Assembly);
|
||||||
|
applicationPartManager.ApplicationParts.Add(assemblyPart2);
|
||||||
|
applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
|
||||||
|
var feature = new MetadataReferenceFeature();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
applicationPartManager.PopulateFeature(feature);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Contains(
|
||||||
|
feature.MetadataReferences,
|
||||||
|
reference => reference.Display.Equals(currentAssembly.Location));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
using Microsoft.AspNetCore.Mvc.Internal;
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||||
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
|
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
|
||||||
|
|
@ -55,6 +56,55 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
|
||||||
Assert.Empty(builder.PartManager.ApplicationParts);
|
Assert.Empty(builder.PartManager.ApplicationParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddRazorViewEngine_AddsMetadataReferenceFeatureProvider()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
var builder = services.AddMvcCore();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
builder.AddRazorViewEngine();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Single(builder.PartManager.FeatureProviders.OfType<MetadataReferenceFeatureProvider>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddRazorViewEngine_DoesNotAddMultipleMetadataReferenceFeatureProvider_OnMultipleInvocations()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
var builder = services.AddMvcCore();
|
||||||
|
|
||||||
|
// Act - 1
|
||||||
|
builder.AddRazorViewEngine();
|
||||||
|
|
||||||
|
// Act - 2
|
||||||
|
builder.AddRazorViewEngine();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Single(builder.PartManager.FeatureProviders.OfType<MetadataReferenceFeatureProvider>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddRazorViewEngine_DoesNotReplaceExistingMetadataReferenceFeatureProvider()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
var builder = services.AddMvcCore();
|
||||||
|
var metadataReferenceFeatureProvider = new MetadataReferenceFeatureProvider();
|
||||||
|
builder.PartManager.FeatureProviders.Add(metadataReferenceFeatureProvider);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
builder.AddRazorViewEngine();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var actual = Assert.Single(
|
||||||
|
builder.PartManager.FeatureProviders.OfType<MetadataReferenceFeatureProvider>());
|
||||||
|
Assert.Same(metadataReferenceFeatureProvider, actual);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddTagHelpersAsServices_ReplacesTagHelperActivatorAndTagHelperTypeResolver()
|
public void AddTagHelpersAsServices_ReplacesTagHelperActivatorAndTagHelperTypeResolver()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,11 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using Microsoft.Extensions.DependencyModel;
|
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -26,10 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
|
||||||
var content = @"
|
var content = @"
|
||||||
public class MyTestType {}";
|
public class MyTestType {}";
|
||||||
|
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var compilationService = GetRoslynCompilationService();
|
||||||
GetDependencyContext(),
|
|
||||||
GetOptions(),
|
|
||||||
GetFileProviderAccessor());
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
"some-relative-path");
|
"some-relative-path");
|
||||||
|
|
@ -53,10 +48,7 @@ this should fail";
|
||||||
var fileProvider = new TestFileProvider();
|
var fileProvider = new TestFileProvider();
|
||||||
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
|
var fileInfo = fileProvider.AddFile(viewPath, fileContent);
|
||||||
|
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
|
||||||
GetDependencyContext(),
|
|
||||||
GetOptions(),
|
|
||||||
GetFileProviderAccessor(fileProvider));
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
|
var relativeFileInfo = new RelativeFileInfo(fileInfo, "some-relative-path");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -77,10 +69,7 @@ this should fail";
|
||||||
var fileContent = "file content";
|
var fileContent = "file content";
|
||||||
var content = @"this should fail";
|
var content = @"this should fail";
|
||||||
|
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var compilationService = GetRoslynCompilationService();
|
||||||
GetDependencyContext(),
|
|
||||||
GetOptions(),
|
|
||||||
GetFileProviderAccessor());
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { Content = fileContent },
|
new TestFileInfo { Content = fileContent },
|
||||||
"some-relative-path");
|
"some-relative-path");
|
||||||
|
|
@ -112,10 +101,7 @@ this should fail";
|
||||||
var fileProvider = new TestFileProvider();
|
var fileProvider = new TestFileProvider();
|
||||||
fileProvider.AddFile(path, mockFileInfo.Object);
|
fileProvider.AddFile(path, mockFileInfo.Object);
|
||||||
|
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var compilationService = GetRoslynCompilationService(fileProvider: fileProvider);
|
||||||
GetDependencyContext(),
|
|
||||||
GetOptions(),
|
|
||||||
GetFileProviderAccessor());
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path);
|
var relativeFileInfo = new RelativeFileInfo(mockFileInfo.Object, path);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -140,14 +126,9 @@ public class MyCustomDefinedClass {}
|
||||||
public class MyNonCustomDefinedClass {}
|
public class MyNonCustomDefinedClass {}
|
||||||
#endif
|
#endif
|
||||||
";
|
";
|
||||||
|
|
||||||
var options = GetOptions();
|
var options = GetOptions();
|
||||||
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
|
options.ParseOptions = options.ParseOptions.WithPreprocessorSymbols("MY_CUSTOM_DEFINE");
|
||||||
|
var compilationService = GetRoslynCompilationService(options: options);
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
|
||||||
GetDependencyContext(),
|
|
||||||
options,
|
|
||||||
GetFileProviderAccessor());
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
"some-relative-path");
|
"some-relative-path");
|
||||||
|
|
@ -170,12 +151,7 @@ public class MyNonCustomDefinedClass {}
|
||||||
fileProvider.AddFile(viewPath, "view-content");
|
fileProvider.AddFile(viewPath, "view-content");
|
||||||
var options = new RazorViewEngineOptions();
|
var options = new RazorViewEngineOptions();
|
||||||
options.FileProviders.Add(fileProvider);
|
options.FileProviders.Add(fileProvider);
|
||||||
|
var compilationService = GetRoslynCompilationService(options: options, fileProvider: fileProvider);
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
|
||||||
GetDependencyContext(),
|
|
||||||
options,
|
|
||||||
GetFileProviderAccessor(fileProvider));
|
|
||||||
|
|
||||||
var assemblyName = "random-assembly-name";
|
var assemblyName = "random-assembly-name";
|
||||||
|
|
||||||
var diagnostics = new[]
|
var diagnostics = new[]
|
||||||
|
|
@ -256,11 +232,8 @@ public class MyNonCustomDefinedClass {}
|
||||||
// Arrange
|
// Arrange
|
||||||
var content = "public class MyTestType {}";
|
var content = "public class MyTestType {}";
|
||||||
RoslynCompilationContext usedCompilation = null;
|
RoslynCompilationContext usedCompilation = null;
|
||||||
|
var options = GetOptions(c => usedCompilation = c);
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var compilationService = GetRoslynCompilationService(options: options);
|
||||||
GetDependencyContext(),
|
|
||||||
GetOptions(callback: c => usedCompilation = c),
|
|
||||||
GetFileProviderAccessor());
|
|
||||||
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
|
@ -274,43 +247,12 @@ public class MyNonCustomDefinedClass {}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Compile_ThrowsIfDependencyContextIsNullAndTheApplicationFailsToCompileWithNoReferences()
|
public void Compile_ThrowsIfNoMetadataReferencesAreDiscoveredAndApplicationFailsToCompile()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var content = "public class MyTestType {}";
|
var content = "public class MyTestType {}";
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var applicationPartManager = new ApplicationPartManager();
|
||||||
dependencyContext: null,
|
var compilationService = GetRoslynCompilationService(applicationPartManager);
|
||||||
viewEngineOptions: GetOptions(),
|
|
||||||
fileProviderAccessor: GetFileProviderAccessor());
|
|
||||||
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
|
||||||
"some-relative-path.cshtml");
|
|
||||||
|
|
||||||
var expected = "The Razor page 'some-relative-path.cshtml' failed to compile. Ensure that your "
|
|
||||||
+ "application's project.json sets the 'preserveCompilationContext' compilation property.";
|
|
||||||
|
|
||||||
// Act and Assert
|
|
||||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
|
||||||
compilationService.Compile(relativeFileInfo, content));
|
|
||||||
Assert.Equal(expected, ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Compile_ThrowsIfDependencyContextReturnsNoReferencesAndTheApplicationFailsToCompile()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var content = "public class MyTestType {}";
|
|
||||||
var dependencyContext = new DependencyContext(
|
|
||||||
new TargetInfo("framework", "runtime", "signature", isPortable: true),
|
|
||||||
Extensions.DependencyModel.CompilationOptions.Default,
|
|
||||||
new CompilationLibrary[0],
|
|
||||||
new RuntimeLibrary[0],
|
|
||||||
Enumerable.Empty<RuntimeFallbacks>());
|
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
|
||||||
dependencyContext: dependencyContext,
|
|
||||||
viewEngineOptions: GetOptions(),
|
|
||||||
fileProviderAccessor: GetFileProviderAccessor());
|
|
||||||
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
|
@ -334,11 +276,7 @@ public class MyNonCustomDefinedClass {}
|
||||||
context.Compilation = context.Compilation.RemoveAllReferences();
|
context.Compilation = context.Compilation.RemoveAllReferences();
|
||||||
});
|
});
|
||||||
var content = "public class MyTestType {}";
|
var content = "public class MyTestType {}";
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var compilationService = GetRoslynCompilationService(options: options);
|
||||||
dependencyContext: GetDependencyContext(),
|
|
||||||
viewEngineOptions: options,
|
|
||||||
fileProviderAccessor: GetFileProviderAccessor());
|
|
||||||
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
"some-relative-path.cshtml");
|
"some-relative-path.cshtml");
|
||||||
|
|
@ -363,10 +301,8 @@ public class MyNonCustomDefinedClass {}
|
||||||
.AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
|
.AddReferences(MetadataReference.CreateFromFile(assemblyLocation));
|
||||||
});
|
});
|
||||||
var content = "public class MyTestType {}";
|
var content = "public class MyTestType {}";
|
||||||
var compilationService = new TestableRoslynCompilationService(
|
var applicationPartManager = new ApplicationPartManager();
|
||||||
dependencyContext: null,
|
var compilationService = GetRoslynCompilationService(applicationPartManager, options);
|
||||||
viewEngineOptions: options,
|
|
||||||
fileProviderAccessor: GetFileProviderAccessor());
|
|
||||||
|
|
||||||
var relativeFileInfo = new RelativeFileInfo(
|
var relativeFileInfo = new RelativeFileInfo(
|
||||||
new TestFileInfo { PhysicalPath = "SomePath" },
|
new TestFileInfo { PhysicalPath = "SomePath" },
|
||||||
|
|
@ -399,7 +335,7 @@ public class MyNonCustomDefinedClass {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
|
private static IRazorViewEngineFileProviderAccessor GetFileProviderAccessor(IFileProvider fileProvider = null)
|
||||||
{
|
{
|
||||||
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
|
var options = new Mock<IRazorViewEngineFileProviderAccessor>();
|
||||||
options.SetupGet(o => o.FileProvider)
|
options.SetupGet(o => o.FileProvider)
|
||||||
|
|
@ -408,38 +344,36 @@ public class MyNonCustomDefinedClass {}
|
||||||
return options.Object;
|
return options.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DependencyContext GetDependencyContext()
|
private static IOptions<RazorViewEngineOptions> GetAccessor(RazorViewEngineOptions options)
|
||||||
{
|
{
|
||||||
var assembly = typeof(DefaultRoslynCompilationServiceTest).GetTypeInfo().Assembly;
|
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
|
||||||
return DependencyContext.Load(assembly);
|
optionsAccessor.SetupGet(a => a.Value).Returns(options);
|
||||||
|
return optionsAccessor.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestableRoslynCompilationService : DefaultRoslynCompilationService
|
private static ApplicationPartManager GetApplicationPartManager()
|
||||||
{
|
{
|
||||||
private readonly DependencyContext _dependencyContext;
|
var applicationPartManager = new ApplicationPartManager();
|
||||||
|
var assembly = typeof(DefaultRoslynCompilationServiceTest).GetTypeInfo().Assembly;
|
||||||
|
applicationPartManager.ApplicationParts.Add(new AssemblyPart(assembly));
|
||||||
|
applicationPartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
|
||||||
|
|
||||||
public TestableRoslynCompilationService(
|
return applicationPartManager;
|
||||||
DependencyContext dependencyContext,
|
}
|
||||||
RazorViewEngineOptions viewEngineOptions,
|
|
||||||
IRazorViewEngineFileProviderAccessor fileProviderAccessor)
|
|
||||||
: base(
|
|
||||||
Mock.Of<IHostingEnvironment>(),
|
|
||||||
GetAccessor(viewEngineOptions),
|
|
||||||
fileProviderAccessor,
|
|
||||||
NullLoggerFactory.Instance)
|
|
||||||
{
|
|
||||||
_dependencyContext = dependencyContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IOptions<RazorViewEngineOptions> GetAccessor(RazorViewEngineOptions options)
|
private static DefaultRoslynCompilationService GetRoslynCompilationService(
|
||||||
{
|
ApplicationPartManager partManager = null,
|
||||||
var optionsAccessor = new Mock<IOptions<RazorViewEngineOptions>>();
|
RazorViewEngineOptions options = null,
|
||||||
optionsAccessor.SetupGet(a => a.Value).Returns(options);
|
IFileProvider fileProvider = null)
|
||||||
return optionsAccessor.Object;
|
{
|
||||||
}
|
partManager = partManager ?? GetApplicationPartManager();
|
||||||
|
options = options ?? GetOptions();
|
||||||
|
|
||||||
protected override DependencyContext GetDependencyContext(IHostingEnvironment hostingEnvironment)
|
return new DefaultRoslynCompilationService(
|
||||||
=> _dependencyContext;
|
partManager,
|
||||||
|
GetAccessor(options),
|
||||||
|
GetFileProviderAccessor(fileProvider),
|
||||||
|
NullLoggerFactory.Instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters.Json.Internal;
|
using Microsoft.AspNetCore.Mvc.Formatters.Json.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Internal;
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
using Microsoft.AspNetCore.Mvc.Razor;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||||
using Microsoft.AspNetCore.Mvc.TagHelpers;
|
using Microsoft.AspNetCore.Mvc.TagHelpers;
|
||||||
|
|
@ -202,10 +203,11 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
Assert.NotNull(descriptor.ImplementationInstance);
|
Assert.NotNull(descriptor.ImplementationInstance);
|
||||||
var manager = Assert.IsType<ApplicationPartManager>(descriptor.ImplementationInstance);
|
var manager = Assert.IsType<ApplicationPartManager>(descriptor.ImplementationInstance);
|
||||||
|
|
||||||
Assert.Equal(3, manager.FeatureProviders.Count);
|
Assert.Collection(manager.FeatureProviders,
|
||||||
Assert.IsType<ControllerFeatureProvider>(manager.FeatureProviders[0]);
|
feature => Assert.IsType<ControllerFeatureProvider>(feature),
|
||||||
Assert.IsType<ViewComponentFeatureProvider>(manager.FeatureProviders[1]);
|
feature => Assert.IsType<ViewComponentFeatureProvider>(feature),
|
||||||
Assert.IsType<TagHelperFeatureProvider>(manager.FeatureProviders[2]);
|
feature => Assert.IsType<TagHelperFeatureProvider>(feature),
|
||||||
|
feature => Assert.IsType<MetadataReferenceFeatureProvider>(feature));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
{
|
{
|
||||||
|
"buildOptions": {
|
||||||
|
"preserveCompilationContext": true
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.AspNetCore.Mvc": "1.0.0-*"
|
"Microsoft.AspNetCore.Mvc": "1.0.0-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"net451": {},
|
"net451": { },
|
||||||
"netcoreapp1.0": {
|
"netcoreapp1.0": {
|
||||||
"imports": [
|
"imports": [
|
||||||
"dnxcore50",
|
"dnxcore50",
|
||||||
"portable-net451+win8"
|
"portable-net451+win8"
|
||||||
],
|
],
|
||||||
"dependencies": {}
|
"dependencies": { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace ControllersFromServicesWebSite
|
||||||
|
{
|
||||||
|
public class AssemblyMetadataReferenceFeatureProvider : IApplicationFeatureProvider<MetadataReferenceFeature>
|
||||||
|
{
|
||||||
|
public void PopulateFeature(IEnumerable<ApplicationPart> parts, MetadataReferenceFeature feature)
|
||||||
|
{
|
||||||
|
var currentAssembly = GetType().GetTypeInfo().Assembly;
|
||||||
|
feature.MetadataReferences.Add(MetadataReference.CreateFromFile(currentAssembly.Location));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,10 +25,15 @@ namespace ControllersFromServicesWebSite
|
||||||
.AddMvc()
|
.AddMvc()
|
||||||
.ConfigureApplicationPartManager(manager => manager.ApplicationParts.Clear())
|
.ConfigureApplicationPartManager(manager => manager.ApplicationParts.Clear())
|
||||||
.AddApplicationPart(typeof(TimeScheduleController).GetTypeInfo().Assembly)
|
.AddApplicationPart(typeof(TimeScheduleController).GetTypeInfo().Assembly)
|
||||||
.ConfigureApplicationPartManager(manager => manager.ApplicationParts.Add(new TypesPart(
|
.ConfigureApplicationPartManager(manager =>
|
||||||
typeof(AnotherController),
|
{
|
||||||
typeof(ComponentFromServicesViewComponent),
|
manager.ApplicationParts.Add(new TypesPart(
|
||||||
typeof(InServicesTagHelper))))
|
typeof(AnotherController),
|
||||||
|
typeof(ComponentFromServicesViewComponent),
|
||||||
|
typeof(InServicesTagHelper)));
|
||||||
|
|
||||||
|
manager.FeatureProviders.Add(new AssemblyMetadataReferenceFeatureProvider());
|
||||||
|
})
|
||||||
.AddControllersAsServices()
|
.AddControllersAsServices()
|
||||||
.AddViewComponentsAsServices()
|
.AddViewComponentsAsServices()
|
||||||
.AddTagHelpersAsServices();
|
.AddTagHelpersAsServices();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
"emitEntryPoint": true,
|
"emitEntryPoint": true
|
||||||
"preserveCompilationContext": true
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
"Microsoft.NETCore.Platforms": "1.0.1-*",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue