Prevent Nancy from Caches all file system path evaluations - nancy

I'm facing a problem that the size of my static content directory is too big and contains a lot of sub-directories( about 22 GB) and when I run my code it takes about 30 mins to create a new instance from NancyHost because it scans all the sub-directories in the main directory for better performance.Below is the code on how I specify the static content directory and how I create the nancy host
public class ApplicationBootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("/", #"MyDirectory"));
base.ConfigureConventions(nancyConventions);
}
}
ApplicationBootstrapper ApplicationBootstrapper = new ApplicationBootstrapper();
nancyHost = new NancyHost(ApplicationBootstrapper, new Uri(String.Format("http://localhost:{0}/", NancyPort)));
nancyHost.Start();
My question is how to prevent nacny from scanning the directory on the startup?

Related

In VS Installer Project, Commit() is not working properly

Using the Visual Studio Installer Project, I included the initial setup project in Install and Commit in Custom Actions that will perform the downloading of the cabinet file under the Windows\Temp\Target Folder folder. Consequently, the zip file will be unzipped.
I used async/await for the first time in DownloadCatalog(), but the zip file wasn't properly downloaded, even though the directory was created. I assumed the installing process stopped the downloading process. I then changed it.
I created the installation file without async. Then I ran it, but the result was the same. This code works fine when running it in an independent project. Do you have any suggestions?
namespace IntialSetupApp
{
[RunInstaller(true)]
public partial class IntialInstallApp : System.Configuration.Install.Installer
{
private readonly string temp = #"C:\Windows\Temp\Target Folder\";
private readonly string zipUrl = #"https://thank.you/so.much";
private readonly string catalog = #"C:\Windows\Temp\Target Folder\whateverXML.xml";
public IntialInstallApp()
{
InitializeComponent();
}
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
Directory.CreateDirectory(temp);
DownloadCatalog();
}
private Task DownloadCatalog()
{
try
{
string fileName = Path.Combine(temp, "ZippedCab.cab");
Uri uri = new Uri(url);
using (WebClient client = new WebClient())
{
client.DownloadFile(uri, fileName);
}
UnzipFile(fileName);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return Task.FromResult(true);
}
private Task UnzipFile(string filePath)
{
try
{
CabInfo cab = new CabInfo(filePath);
cab.Unpack(temp);
return Task.FromResult(true);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return Task.FromResult(false);
}
}
}
+Update
With the above code, I created the console project independently, and it created the folder and completed downloading the file. Therefore, it seems that installer prevents modifying other folders. Is there any workaround way?
The reason was The request was aborted: Could not create SSL/TLS secure channel., so I updated the code with this. Then it works fine.

MEF can't find module's views when dll in subdirectory

I try to make a little application with Prism and MEF in order to learn how it works. I'm stuck on a fairly frustrating problem.
I would like to have a "Modules" subdirectory in my base app directory where I copy all the module's dll as a post build event.
These modules are MVVM app with View and ViewModel.
My problem is : When I copy my module's dll in the main app directory, the views are displayed in the shell, but when my modules are in the subdirectory, nothing is displayer.
My modules and their parts are found but according to fuslogvw the views can't be found :
* Assembly Binder Log Entry (27/11/2015 # 16:45:28) *
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\Users\mouarf\Downloads\Prism-Samples-Wpf-master\Prism-Samples-Wpf-master\HelloWorld\HelloWorld\bin\Debug\HelloWorld.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = ModuleB.resources, Version=1.0.0.0, Culture=en-US, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/Users/mouarf/Prism/HelloWorld/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = HelloWorld.vshost.exe
Calling assembly : ModuleB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\Users\mouarf\Downloads\Prism-Samples-Wpf-master\Prism-Samples-Wpf-master\HelloWorld\HelloWorld\bin\Debug\HelloWorld.vshost.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/mouarf/Prism/HelloWorld/bin/Debug/en-US/ModuleB.resources.DLL.
LOG: Attempting download of new URL file:///C:/Users/mouarf/Prism/HelloWorld/bin/Debug/en-US/ModuleB.resources/ModuleB.resources.DLL.
LOG: Attempting download of new URL file:///C:/Users/mouarf/Prism/HelloWorld/bin/Debug/en-US/ModuleB.resources.EXE.
LOG: Attempting download of new URL file:///C:/Users/mouarf/Prism/HelloWorld/bin/Debug/en-US/ModuleB.resources/ModuleB.resources.EXE.
LOG: Attempting download of new URL file:///C:/USERS/Mouarf/PRISM/HELLOWORLD/BIN/DEBUG/MODULES/en-US/ModuleB.resources.DLL.
LOG: Attempting download of new URL file:///C:/USERS/Mouarf/PRISM/HELLOWORLD/BIN/DEBUG/MODULES/en-US/ModuleB.resources/ModuleB.resources.DLL.
LOG: Attempting download of new URL file:///C:/USERS/Mouarf/PRISM/HELLOWORLD/BIN/DEBUG/MODULES/en-US/ModuleB.resources.EXE.
LOG: Attempting download of new URL file:///C:/USERS/Mouarf/PRISM/HELLOWORLD/BIN/DEBUG/MODULES/en-US/ModuleB.resources/ModuleB.resources.EXE.
LOG: All probing URLs attempted and failed.
I don't know why MEF look in "modules\en-US\", I think it's probably why it doesn't find any views, but I couldn't find how to specify otherwise.
My bootstrapper :
public class Bootstrapper : MefBootstrapper
{
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules");
DirectoryCatalog catalog = new DirectoryCatalog(path, "*.dll");
this.AggregateCatalog.Catalogs.Add(catalog);
}
protected override DependencyObject CreateShell()
{
return this.Container.GetExportedValue<MainWindow>();
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (MainWindow)this.Shell;
Application.Current.MainWindow.Show();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
}
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
}
My modules :
[ModuleExport(typeof(ModuleAModule))]
public class ModuleAModule : IModule
{
IRegionManager _regionManager;
[ImportingConstructor]
public ModuleAModule(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void Initialize()
{
_regionManager.RegisterViewWithRegion(RegionNames.RightRegion, typeof(ViewA));
}
}
My views :
/// <summary>
/// Interaction logic for ViewA.xaml
/// </summary>
[Export]
public partial class ViewA : UserControl
{
public ViewA()
{
InitializeComponent();
}
}
My viewmodels :
[Export]
public class ViewAViewModel : BindableBase
{
private string _title = "Module A";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
}
Anyone ?
Edit :
Here's the solution for who whould like to take a look : HelloWorldPrismMef
Edit 2 :
The investigation still goes on, I discovered the really handy mefx ! So my problem seems to be :
[Part] ModuleA.ModuleAModule from: DirectoryCatalog (Path="Modules")
[Primary Rejection]
[Export] ModuleA.ModuleAModule (ContractName="Prism.Modularity.IModule")
[Import] ModuleA.ModuleAModule..ctor (Parameter="regionManager", ContractName="Prism.Regions.IRegionManager")
[Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No exports were found that match the constraint contract name
ContractName Prism.Regions.IRegionManager
RequiredTypeIdentity Prism.Regions.IRegionManager n'a été trouvée.
at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)
at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id)
Does that mean that I need to Export a IRegionManager class ?
The log you have posted is for an attempt to load a resource .dll, something that MEF will never load (resource .dlls are used to store application resource information, like strings for internationalization). You should look for errors that do not mention resource .dlls.
Also, it seems to me you are attempting to edit the Prism Library HelloWorld example from GitHub. This particular example has tight coupling with ModuleA (by that I mean that ModuleA is used as a project dependency in HelloWorld) and to my knowledge you can not simply move the ModuleA.dll from the main folder to a modules folder and expect it to work.
My suggestion would be to add a new project, set that to output to a modules folder and see if that loads (leaving the ModuleA project alone). Or you could remove the reference from the HelloWorld project and use the post build event.
Now regarding the loading of modules from a directory, in my humble opinion, you are over complicating it. All you need is
AgregateCatalog.Catalogs.Add(new DirectoryCatalog(#".\Modules"));
Or presuming you have a convention that specifies a pattern for module file names that resembles AppName.Modules.[ModuleNameHere].dll (eg: AppName.Modules.LoginModule.dll you could use something like this to load the modules
AgregateCatalog.Catalogs.Add(new DirectoryCatalog(#".\Modules", "AppName.Modules.*Module.dll"));
Although this does not seem the case here, if you ever try to load modules from a zone deemed as untrustworthy, the default security policy is to ignore the module. This would happen if you attempt to run the application over a network connection like Windows Share. For this scenario you need to add these instructions to App.config
<runtime>
<loadFromRemoteSources enabled="true" />
</runtime>
These should be added after <startup /> section.
Hope this helps you.
Edit:
Does that mean that I need to Export a IRegionManager class ?
No, that's just complaining because mefx has not loaded the assembly that exports it (Prism.Wpf.dll I think it is called).
Personally I found mefx.exe to be cumbersome; I prefer the GUI version
Now regarding your code, I took a look at the GitHub repository and made some changes but not that many (had some issues with references with ModuleC so I had to remove and add again Prism.Mef & company):
Removed the PostBuildEvent from Infrastructure project
Changed the PostBuildEvent from the module projects. This needs some explaining:
all macros come appended with the directory delimiter "\" so you do not need to add it (I am reffering to $(OutDir)\Modules => $(OutDir)Modules).
COPY/XCOPY require the destination path to end with a delimiter or the destination path will be intepreted as a destinaiton directory ( $(OutDir)Modules => *$(OutDir)Modules* ).
Destination directory needs to exist (so first command should be MKDIR)
I also commented (lines that start with REM are comments) out the command that copies the .pdb because I do not think it is needed and added the /z flag to XCOPY.
Added ILoggerFacade as a dependency to demonstrate that the modules actually load. If you run the application from the Visual Studio Debugger, you will see some messages in the debug window.
Added <loadFromRemoteSources enabled="true" /> in App.config => <configuration /> => <runtime /> so I can run the app over a mounted partition where the project is stored.
All of this is in the PR.
Now regarding why it will not auto-display the views in the regions, I can not say yet. I will keep investigating during my free time, but you might have better luck asking Brian Lagunas as he is one of the developers of Prism.
Edit 2:
As I was looking at Brian Lagunas's profile I saw he answered this post that luckily solves the issue.
Will also add a PR to GitHub.

Nancy fails to find static content in custom convention

I've set up a Nancy bootstrapper to serve static content from a non-default directory path (it's self hosted Nancy).
Strangely, the following works for the custom View location convention but not either of the js or css static content conventions (and yes, both files and folders exist at these locations!). My attempts at trying to resolve this are further compounded as I haven't figured out how to log errors which occur when static content is not found.
using System;
using System.IO;
using Nancy;
using Nancy.Conventions;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;
namespace MyApp
{
public class ApplicationBootstrapper : DefaultNancyBootstrapper
{
private const string RELATIVE_PATH_TO_SOURCE = #"../static/MyApp/";
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("js", string.Concat(RELATIVE_PATH_TO_SOURCE, "Scripts/")));
nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("css", string.Concat(RELATIVE_PATH_TO_SOURCE, "Content/")));
this.Conventions.ViewLocationConventions.Add((viewName, model, context) =>
{
return string.Concat(RELATIVE_PATH_TO_SOURCE, "Views/", viewName);
});
this.Conventions.ViewLocationConventions.Add((viewName, model, context) =>
{
return string.Concat(RELATIVE_PATH_TO_SOURCE, "Views/", context.ModuleName, "/", viewName);
});
base.ConfigureConventions(nancyConventions);
}
protected override IRootPathProvider RootPathProvider
{
get
{
return new MyRootPathProvider();
}
}
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
pipelines.OnError += (ctx, ex) =>
{
Console.WriteLine("RootPath : {0}", DebugRootPathProvider.RootPath);
Console.WriteLine("Unhandled error on request: {0} : {1}", ctx.Request.Url, ex.Message); //HACK
Console.WriteLine(ex.StackTrace); //HACK poor man's logging
return null;
};
}
}
public class MyRootPathProvider : IRootPathProvider
{
public static readonly string RootPath;
static MyRootPathProvider()
{
RootPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
}
public string GetRootPath()
{
return RootPath;
}
}
}
The output from Chrome and ProcMon is as follows:
How should I:
Log errors occurring with not found js and css files?
Resolve the 404 errors with the static file conventions?
Instead of logging you can use sysinternals process monitor and look for what files the nancy process (exe or IIS worker process) are attempting to read.
I had problems with serving static files (in my case js files) in a self host environment as well. They were not recognized at all, not even in the default "Content" folder. My solution: I installed the Microsoft StaticFiles NuGet Package.
In the startup class, register a static files folder like this:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseStaticFiles("/Scripts");
app.MapSignalR();
app.UseNancy();
}
}
This way, all files and subfolders in the "Scripts" folder are served as static files. There is also an overload of the UseStaticFiles() function that lets you map a physical path to a virtual path.
Important here: the call to UseNancy() has to be the very last, otherwise everything after it won't work. I also tried to combine it with SignalR, as you can see above, and there the UseNancy() call had to be at the end as well.

What is the best way to store user specific files in Wicket?

I am creating a file that is user specific. This file is basically a results csv that is created with the option for the user to download or not. When the user leaves the page, or ends their session I want to be able to delete this file. What is the best way to handle this?
Currently I am using the File class for Java.
Thanks!
You don't have to write a file in the first place. Create the content on the fly and stream it back to the client. Wicket has a few classes in the package org.apache.wicket.request.resource to help with that.
As a starting point, look at Wicket 6 resource management and Wicket 1.5 Mounting resources
You basically mount a resource in the WicketApplication.init():
mountResource("somePath/${param1}/${param2}", new SomeResourceReference());
Than the SomeResourceReference:
public class SomeResourceReference extends ResourceReference {
#Override
public IResource getResource() {
return new SomeResource();
}
}
And finally in SomeResource:
public class SomeResource extends AbstractResource {
#Override
public AbstractResource.ResourceResponse
newResourceResponse(Attributes attributes) {
// get the parameters
PageParameters parameters = attributes.getParameters();
final String param1 = parameters.get("param1").toStringObject();
AbstractResource.ResourceResponse response
= new AbstractResource.ResourceResponse();
response.setContentType("application/CSV");
response.setCacheDuration(Duration.NONE);
response.setCacheScope(WebResponse.CacheScope.PRIVATE);
response.setContentDisposition(ContentDisposition.INLINE);
response.setWriteCallback(new AbstractResource.WriteCallback() {
#Override
public void writeData(final Attributes attributes) throws IOException {
// create your data here
attributes.getResponse().write(dataAsString);
}
});
return response;
}
}
Wicket doesn't control destroying the session. It is the concern of the servlet container you are using.
If you want to create a file in Wicket and delete the file when the session is destroyed or user want logout, it has two parts:
User logout (in Wikcet)
Store the file path or the file reference in the WebSession (Wicket)
Override the method invalidate() of your WebSession or AutheticatedWebSession, see http://ci.apache.org/projects/wicket/apidocs/6.x/org/apache/wicket/protocol/http/WebSession.html#invalidate%28%29
Session destroyed
Store the file path or the file reference into the container session and write your listener and add it to the your servlet context (e.g. tomcat using web.xml file).
See http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionListener.html

silverlight 4, dynamically loading xap modules

I know that it is possible to load xap modules dynamically using Prism or MEF framework. However, I'd like not to use those frameworks; instead load my xap files manually. So, I created the following class (adapted from internet):
public class XapLoader
{
public event XapLoadedEventHandler Completed;
private string _xapName;
public XapLoader(string xapName)
{
if (string.IsNullOrWhiteSpace(xapName))
throw new ArgumentException("Invalid module name!");
else
_xapName = xapName;
}
public void Begin()
{
Uri uri = new Uri(_xapName, UriKind.Relative);
if (uri != null)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += onXapLoadingResponse;
wc.OpenReadAsync(uri);
}
}
private void onXapLoadingResponse(object sender, OpenReadCompletedEventArgs e)
{
if ((e.Error == null) && (e.Cancelled == false))
initXap(e.Result);
if (Completed != null)
{
XapLoadedEventArgs args = new XapLoadedEventArgs();
args.Error = e.Error;
args.Cancelled = e.Cancelled;
Completed(this, args);
}
}
private void initXap(Stream stream)
{
string appManifest = new StreamReader(Application.GetResourceStream(
new StreamResourceInfo(stream, null), new Uri("AppManifest.xaml",
UriKind.Relative)).Stream).ReadToEnd();
XElement deploy = XDocument.Parse(appManifest).Root;
List<XElement> parts = (from assemblyParts in deploy.Elements().Elements()
select assemblyParts).ToList();
foreach (XElement xe in parts)
{
string source = xe.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
StreamResourceInfo streamInfo = Application.GetResourceStream(
new StreamResourceInfo(stream, "application/binary"),
new Uri(source, UriKind.Relative));
asmPart.Load(streamInfo.Stream);
}
}
}
public delegate void XapLoadedEventHandler(object sender, XapLoadedEventArgs e);
public class XapLoadedEventArgs : EventArgs
{
public Exception Error { get; set; }
public bool Cancelled { get; set; }
}
The above code works fine; I can load any xap the following way:
XapLoader xapLoader = new XapLoader("Sales.xap");
xapLoader.Completed += new XapLoadedEventHandler(xapLoader_Completed);
xapLoader.Begin();
Now, I have a UserControl called InvoiceView in the Sales.xap project, so I would like to instantiate the class. In the current project (Main.xap) I added reference to Sales.xap project, however, since I load it manually I set "Copy Local = False". But when executed, the following code throws TypeLoadException:
Sales.InvoiceView view = new Sales.InvoiceView();
It seems the code can't find InvoiceView class. But I checked that XapLoader's initXap() method was successfully executed. So why the code can't find InvoiceView class? Can someone help me with this problem?
This is based on the asker's self-answer below, rather than the question.
If you delete a project/module the output DLLs/XAP files do hang around. If you click the "show all files" button you will see some these left-over output files in your clientbin, bin and obj folders of related projects.
You can delete them individually from the project, or, when in doubt, search for all BIN and OBJ (e.g. using desktop explorer) and delete all those folders. The BIN/CLIENTBIN/OBJ folders will be recreated when needed (this the job that the "clean" option in Visual Studio should have done!)
Hope this helps.
Ok, I found the cause. The above code works. After creating a new silverlight project (Sales.xap) I happened to compile my solution once. Then I deleted App class in the Sales.xap and renamed default MainPage class to SalesView. However, no matter how many times I compile my solution, Visual Studio's development web server was loading the first version of Sales.xap (where from?), so my code couldn't find SalesView. In my host Asp.Net project I set development server's port to a different port number, and the problem gone. So the problem was with Visual Studio's development server. Apparently it is keeping compiled xap files in some temporary folder, and doesn't always update those xap files when source code changed.
What I do to avoid such problems when executing freshly compiled Silverlight is clear the browser cache, chrome even has a clear silverlight cache ;)
this XAP Cache phenomena is often due to the visual studio embedded web server (ASP.NET Development Server).
Just stop the occurence of this server and the cache will be cleared.
Start again your project and the latest build of your xap is called.

Resources