How can I fix compilation for relative paths using StackExchange.Precompilation? - stackexchange

For https://github.com/StackExchange/StackExchange.Precompilation:
We have some shared views in separate library where we have installed StackExchange.Precompilation. We have to load those views along with the normal web project's views. We have the latest version of StackExchange.Precompilation installed from NuGet in both projects. I am doing the assembly loading like this:
// Register precompiled view engine
ViewEngines.Engines.Clear();
List<Assembly> viewAssemblies = new List<Assembly> { typeof(HomeController).Assembly };
viewAssemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.ToLower().Contains(".web")));
Log.Debug().Message("Looking for views in: {0}", string.Join(", ", viewAssemblies.Select(a => a.FullName))).Write();
ViewEngines.Engines.Add(new PrecompiledViewEngine(viewAssemblies.ToArray()));
In the web project, we return views the normal way: return View("Index");
When using PrecompiledViewEngine we get an error when trying to render relative names like that:
The view 'Index' or its master was not found or no view engine supports the searched locations.
The following locations were searched:
~/util/Views/Example/Index.cshtml
~/util/Views/Shared/Index.cshtml
util is the alias of the application in IIS. We don't have any areas registered.
When I copied the PrecompiledViewEngine class from GitHub - it worked! Am I missing something that will make the version distributed through NuGet work?

Copying the code over turned out not to work. I must have been trying something else at the time that made it work for that specific case.
The problem is actually a bug in StackExchange.Precompilation. I've created an issue there: https://github.com/StackExchange/StackExchange.Precompilation/issues/12

Related

ABP Framework can't acces virtual files in Deploy

I'm working with the ABP Framework and I'm implementing my own mail templates.
The project was made using the abp project template. I created the template in my Application module: Acme.Bookstore.Application/Assets/Templates/MyEmailTemplate.tpl. I edited the properties of the file to be embedded.
Then I made an instance of the template definition provider as follows:
public class MyEmailTemplateDefinitionProvider : TemplateDefinitionProvider
{
public override void Define(ITemplateDefinitionContext context)
{
context.Add(
new TemplateDefinition(
MyEmailTemplates.MyEmailTemplate,
displayName: LocalizableString.Create<AccountResource>($"TextTemplate:{MyEmailTemplates.MyEmailTemplate}"),
layout: StandardEmailTemplates.Layout,
localizationResource: typeof(AccountResource)
).WithVirtualFilePath($"Assets/Templates/MyEmailTemplate.tpl", true)
);
}
}
Then I added the following lines to my BookstoreApplicationModule.cs
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BookstoreApplicationModule>("Acme.Bookstore");
});
I did all this following this documentation: https://docs.abp.io/en/abp/5.3/Virtual-File-System
When debugging locally all works well, but when I deploy the project it can't access the template file. The error is as follows:
Volo.Abp.AbpException: Could not find a file/folder at the location: Assets/Templates/MyEmailTemplate.tpl
I already tried adding the AddEbedded call in the HttpApi.Host module but got the same result. I don't know what I'm missing.
For the record, I'm deploying in an Ubuntu server, but that shouldn't matter.
The problem was that the embedded files weren't being added to the VirtualFileSystem. It worked in develpment because the framework calls:
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
... Some code ...
options.FileSets.ReplaceEmbeddedByPhysical<BookstoreApplicationModule>(
Path.Combine(hostingEnvironment.ContentRootPath,
$"..{Path.DirectorySeparatorChar}Acme.Bookstore.Application"));
});
}
So the problem didn't arise until I did a dotnet publish.
I could not figure out why it wasn't working on the Application module but moving the files to the Domain.Shared module fixed it.
I guess that there is some package or setting missing on the other module but this solution is enough for me.

Sencha package for both classic and modern

Is it possible to create a package more likely a framework package for a modern(phone) and classic(desktop) theme? My question is similar to this one.
I tried creating a package with a classic folder (following this post package.json) then I tried to use Ext.require to call and render views on-demand.
Code:
let command = Ext.String.format(
'{0}.classic.src.view.{1}.{2}View',
namespace,
screen.toLowerCase(),
screen
);
Ext.require(command, function () {
console.log('hello');
xtype = screen.toLowerCase() + 'view';
if (!menuview.getStore()) {
console.log(
'Store not yet available from viewModel binding for ' + screen
);
return;
}
if (!centerview.getComponent(xtype)) {
centerview.add({
xtype: xtype,
itemId: xtype,
heading: node.get('text'),
});
}
centerview.setActiveItem(xtype);
menuview.setSelection(node);
vm = me.getViewModel();
vm.set('heading', node.get('text'));
});
Let's say I have a DashboardView.js on my package, and when I tried to call that on Ext.require, it fails to load the file. I am wondering what am I missing to render my views on-demand.
Hoping to find an answer here. Thanks!
This is called a universal application. There is a really detailed guide showing how you structure and build your application. You end up with two apps... one is classic and one is modern... but you can have shared files like controllers and viewmodels. You can also do this just with modern and use profiles to change xtypes based on phone, tablet or PC. Universal App Guide
You can generate a default starter application that build the directory structure and also the build scripts. It is really very nice. This is the crux behind the model view controller. YOu put the data is the viewModel, the rules/events are in the viewController and all your view classes can be based on the device.
This will build a universal app sample.
sencha -sdk /home/XXX/sencha-sdks/ext-7.3.0 generate app --ext MyApp ./MyApp
if this is in /home/XXX/work/MyApp enter this into your browser:
To run the classic app:
/home/XXX/work/MyApp/index.html?profile=classic
To run the modern app:
/home/XXX/work/MyApp/index.html?profile=modern
Not sure if this answers your question.... I hope it does.

MEF Parts not found for deployed app, but found in Debug mode

I checked a lot of MEF questions here but I can't imagine what my problem is. Here's what's happening:
I have a desktop WPF app that I'm deploying with AdvancedInstaller. I use .NET 4.0 and MEF to compose parts. Some parts are in the main project, so they are inside the app.exe file. Other parts are inside class libraries that reference the main project, so they are inside somename.dll files.
The problem:
While running the app from VS, both in Debug and in Release, everything is fine. Once I deploy the app, some of the dlls say that they have no parts (zero) to export.
I checked the following:
all dlls are available in the deployment and the catalog is finding the files
the export types and names are correct, after all, everything is working while in Visual Studio
when I try to add the parts from the dlls, I get that the number of parts is zero ONLY IN DEPLOYMENT.
This is the code that's not findind parts in the deployed app:
var catalog = new AggregateCatalog();
string path = Environment.CurrentDirectory.ToString();
DirectoryCatalog qualitycontrol = new DirectoryCatalog(".", "QualityControl.exe"); //this is my main assembly
DirectoryCatalog qualitymix;
catalog.Catalogs.Add(qualitycontrol); //this finds the parts and always works fine
if (File.Exists(path + #"\QualityMix.dll"))
{
qualitymix = new DirectoryCatalog(".", "QualityMix.dll"); //the file exists in the deployment
catalog.Catalogs.Add(qualitymix); //the "qualitymix" catalog shows more than 20 parts if run with VS, but 0 parts in deployment
}
The only thing that works (but it's very slow to start the app) is the following:
var catalog = new DirectoryCatalog(".", "*");
This has the problem that it needs to check more than 100 files present in the working directory, and I cannot deploy my plugin dlls in a different dir.
Why is it that a DirectoryCatalog looking at all files finds the parts, but a DirectoryCatalog looking at a single part does not? How can I debug this issue if it only happens in the deployed app?
---Edit: this problem is only happening with certain dlls, the files are found and for other dlls the parts are also found. I'm using the same Export/Import procedure in all dlls, but somehow some of them show no parts in deployment
Anything you can suggest will be helpfull, thank you guys!
NEW INFO!
I tried loading my dll with an AssemblyCatalog. It works in Visual Studio (Debug and Release) but when deployed I get the following errors:
1st try:
if (File.Exists(path + #"\QualityMix.dll"))
{
qualitymix = new AssemblyCatalog(Assembly.LoadFile(path + #"\QualityMix.dll")); //file is loaded and parts found in VS
catalog.Catalogs.Add(qualitymix);
}
Error: The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018).
Second try:
if (File.Exists(path + #"\QualityMix.dll"))
{
var name = AssemblyName.GetAssemblyName(path + #"\QualityMix.dll");
qualitymix = new AssemblyCatalog(Assembly.Load(name));
catalog.Catalogs.Add(qualitymix);
}
Error: Could not load file or assembly 'QualityMix.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.
I've looked for questions about these errors but nothing has been helpful so far. All projects are built for All CPUs, and the references look ok (this dll uses the same references as other projects that are loading ok).
Edit 2:
I tried the suggestion by #SuryaBhaskar to use LoadFrom instead of Load
if (File.Exists(path + #"\QualityMix.dll"))
{
qualitymix = new AssemblyCatalog(Assembly.LoadFrom(path + #"\QualityMix.dll"));
catalog.Catalogs.Add(qualitymix);
}
But I get the same error: Could not load file or assembly 'QualityMix.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format.
I managed to solve this issue by moving the code of the problematic dll to a new project. This solved the issue, somehow... though the reason remains a mistery to me.
Use LoadFrom instead of LoadFile or Load.If you use Load it will have conflicts with other assemblies on current AppDomain

gruntjs / angularjs - optional development config?

Like most js web apps we have a config.js file that contains global config information about the app, base api urls and such. These values are often different in local development than in production.
I've looked at answers like: Development mode for AngularJS using GruntJS, and also things like grunt-replace for creating an on-the-fly config file.
My issue is that the "development" part varies from developer to developer, we all need a version of the API setup so the base api urls will be different. I'd like to allow each developer to override specific variables in the config in a way that doesn't require them to commit that info to the git repo (I agree that this isn't best practice, everything should be in the repo, but as this is only 1/2 variables for this project I can overlook it)
Any ideas on how to achieve this setup?
You can use grunt-preprocess. I would have production (and dev-server, etc) values in a file, say env.json. You could use grunt to look for an optional file, say overrides.json or developer.json, which would extend/overwrite the values from env.json.
var envFile = require('./env.json');
You can create command line options to grunt with grunt.option, e.g. var env = grunt.option('env') || undefined;, which could be used to turn off overriding.
You can get data from the optional file using fs.existsSync:
var fs = require('fs');
var developerFile;
if (fs.existsSync('./developer.json')) {
developerFile = require('./developer.json');
}
The simplest way to define the grunt-preprocess context would be to use the developer.json file if present, or the env.json file if not:
context: developerFile ? developerFile : envFile;
This requires the developer file to be complete. An alternative is to extend the envFile with options from developerFile if it's present.
In my project, we use different config files (which are basically files with JS object). So every developer has his app/configs/developer/config.js file, which is not comited in the source control, so every developer has his own setup. Project uses link to app/scripts/config.js by default and this file is just a soft link to developers config file. However, there are also app/configs/staging/config.js and app/configs/production/config.js files, which are replaced when using gruntjj to build project. Those configs are just copied to build solution instead of soft linked file.
I hope that makes sense..

built ExtJs 4.2, app doesn't run without old classes

I minified/built my app that uses ExtJS 4.2.0 (free version) using Sencha SDK Tools 2.0.0 beta3, and the app was built successfully. However, when I try deleting the old "app" folder containing my old classes, the app no longer works.
I also tried generating a new app using Sencha CMD 4.0.1.45 and then adding my classes, but the results are the same.
I am confused why this happens, because as I understood it, your old classes are not needed to deploy production app. In fact, the only javascript files you need to include in your "index.html" file are "ext.js" and "app-all.js".
I used Firebug and saw in the DOM that the app, along with my classes, are loaded.
I also noticed that "app-all.js" defines classes like this:
Ext.define("MyApp.view.MyClass"...
Is this really how it is supposed to behave? or am I missing something?
Thanks in advance!
Okay, I got it. A .js file in my application calls Ext.require on itself, causing the app wiring go crazy.

Resources