I am using the latest VS.2017 updates and templates for an MVC .NET Core web application. I decided I wanted ViewComponents in an external assembly since I read several posts that indicated it was not possible without odd tricks.
I have my main web application and then I created a .NET Framework class library named MySite.Components which is the "external assembly". In it I installed the ViewFeatures NuGet. I created my View component CSHTML in its /Views/Shared/Components/GoogleAdsense/Default.cshtml.
I noticed that my CSPROJ already has the GoogleAdSense as an embedded resource:
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<EmbeddedResource Include="Views\Shared\Components\GoogleAdsense\Default.cshtml" />
</ItemGroup>
The view component is actually quite simple:
namespace MySite.Components.ViewComponents {
[ViewComponent(Name = "GoogleAdsense")]
public class GoogleAdsense : ViewComponent {
public async Task<IViewComponentResult> InvokeAsync(string adSlot, string clientId, string adStyle = "")
{
var model = await GetConfigAsync(adSlot, clientId, adStyle);
return View(model);
}
private Task<GoogleAdUnitCompModel> GetConfigAsync(string adSlot, string clientId, string adStyle)
{
GoogleAdUnitCompModel model = new GoogleAdUnitCompModel
{
ClientId = clientId, // apparently we can't access App_Data because there is no AppDomain in .NET core
SlotNr = adSlot,
Style = adStyle
};
return Task.FromResult(model);
}
}
}
Then in the main project (the ASP.NET Core web application) I installed the File Provider NuGet and modified my Startup:
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Add(new EmbeddedFileProvider(
typeof(MySite.Components.ViewComponents.GoogleAdsense).GetTypeInfo().Assembly,
"MySite.Components.ViewComponents"
));
});
Then I try to use the view component in a view like this:
@using MySite.Components.ViewComponents
:
@Component.InvokeAsync(nameof(GoogleAdsense), new { adSlot = "2700000000", clientId = "ca-pub-0000000000000000", adStyle="" })
And I get an error saying
*InvalidOperationException: A view component named 'GoogleAdsense' could not be found.*
Also tried using the notation without nameof() that uses a generic parameter for InvokeAsync but that fails too but with
*"Argument 1: cannot convert from 'method group' to 'object'"*
And using the TagHelper form simply renders it as an unrecognized HTML:
<vc:GoogleAdsense adSlot = "2700000000" clientId = "ca-pub-0000000000000000"></vc:GoogleAdsense>
Finally, on the Main Assembly (the actual web application) I used the GetManifestResourceNames() on the external assembly type to verify it was embedded and the returned list had it listed as:
[0] = "MySite.Components.Views.Shared.Components.GoogleAdsense.Default.cshtml"