Я пытаюсь реализовать общий подход для предоставления возможности для разных сборок в моем веб-решении использовать встроенные файлы JavaScript и CSS из встроенных ресурсов. This blog post показывает технику с использованием VirtualPathProvider. Это прекрасно работает, но VirtualPathProvider должен быть включен в каждую сборку, содержащую встроенные ресурсы.ASP.NET с использованием встроенных ресурсов в Bundling
Я пытался усилить VirtualPathProvider с поста в блоге, так что сборка может быть передана в него, и он загружает ресурс из его сборки:
public EmbeddedVirtualPathProvider(VirtualPathProvider previous, Assembly assembly)
{
this.previous = previous;
this.assembly = assembly;
}
На этапе инициализации считывает все внедренные ресурсы пропущенных сборка:
protected override void Initialize()
{
base.Initialize();
this.assemblyResourceNames = this.assembly.GetManifestResourceNames();
this.assemblyName = this.assembly.GetName().Name;
}
И GetFile
считывает содержимое из пройденной сборки:
public override VirtualFile GetFile(string virtualPath)
{
if (IsEmbeddedPath(virtualPath))
{
if (virtualPath.StartsWith("~", System.StringComparison.OrdinalIgnoreCase))
{
virtualPath = virtualPath.Substring(1);
}
if (!virtualPath.StartsWith("/", System.StringComparison.OrdinalIgnoreCase))
{
virtualPath = string.Concat("/", virtualPath);
}
var resourceName = string.Concat(this.assembly.GetName().Name, virtualPath.Replace("/", "."));
var stream = this.assembly.GetManifestResourceStream(resourceName);
if (stream != null)
{
return new EmbeddedVirtualFile(virtualPath, stream);
}
else
{
return _previous.GetFile(virtualPath);
}
}
else
return _previous.GetFile(virtualPath);
}
Проверка ресурса внедренный ресурс этого узла, проверяя имена ресурсов для чтения в Initialize
метода:
private bool IsEmbeddedPath(string path)
{
var resourceName = string.Concat(this.assemblyName, path.TrimStart('~').Replace("/", "."));
return this.assemblyResourceNames.Contains(resourceName, StringComparer.OrdinalIgnoreCase);
}
Я перенес EmbeddedVirtualPathProvider
класс основного веб-проекта (Projecta), так что это Безразлично «т должен быть включен в каждой сборке, содержащей встроенные ресурсы и зарегистрировал его, используя следующий код в Global.asax
:
HostingEnvironment.RegisterVirtualPathProvider(
new EmbeddedVirtualPathProvider(
HostingEnvironment.VirtualPathProvider,
typeof(ProjectB.SomeType).Assembly));
в проекте, содержащий вложенные ресурсы (ProjectB) Я до сих пор создать следующий пакет в PostApplicationStartMethod
:
BundleTable.Bundles.Add(new ScriptBundle("~/Embedded/Js")
.Include("~/Scripts/SomeFolder/MyScript.js")
);
Scripts/MyScript.js
является внедренным ресурсом в ProjectB.
С этим я получаю следующее исключение:
Directory 'C: \ холсты \ ProjectA \ Scripts \ SomeFolder \' не существует. Не удалось начать мониторинг изменений файлов.
Update Полный след стека доступны в this Gist.
Обновление Также сам VirtualPathProvider работает нормально. Если я загрузить файл непосредственно, а не через узел и установить следующую запись в web.config
он загружает встроенный JavaScript из ProjectB:
<system.webServer>
<handlers>
<add name="MyStaticFileHandler" path="*.js" verb="GET,HEAD" type="System.Web.StaticFileHandler"/>
</handlers>
</system.webServer>
Где ваш класс Startup? В ProjectA или ProjectB? –
ProjectA - это пакет NuGet, содержащий VirtualPathProvider. ProjectB еще один пакет NuGet, обеспечивающий некоторую функциональность с просмотрами (их несколько). Проект NuGet PackageB имеет зависимость от проекта NuGetPackage ProjectA. Приложения устанавливают ProjectB NuGetPackages. Поэтому запуск за пределами ProjectA и ProjectB, но ProjectA и ProjectB могут подключаться к PreApplicationStartMethod. –
Кажется, что метод 'IsEmbeddedPath' возвращает' false', тогда как он должен возвращать 'true'. Не могли бы вы рассказать нам значение 'path' и' resourceName' до возникновения ошибки? –