Prevent view caching in Nancy when using the Spark template engine - c#

I'm using a self-hosted Nancy with Spark templates. I've disabled the cache specifically (though in DEBUG is should be disabled by default).
protected override void ApplicationStartup(Nancy.TinyIoc.TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
...
StaticConfiguration.Caching.EnableRuntimeViewDiscovery = true;
StaticConfiguration.Caching.EnableRuntimeViewUpdates = true;
}
However, making changes to the templates while the app is running doesn't seem to work, as the template changes are not picked up.
Is there anything else required to disable views caching?

Since you're application is self hosted, I'm guessing you've either overriden the view location convention to find views as embedded resources in your assembly or have configured your Visual Studio project to copy views into the output directory at compile time. In both cases your application is not running off the view files you have in the Visial Studio project, but rather off copies of them. In that case caching is not the issue.

Ok, managed to get this to work by adding a custom ViewCache in the bootstrapper:
public class MyBootstrapper : DefaultNancyBootstrapper
{
#if DEBUG
protected override IRootPathProvider RootPathProvider
{
get
{
// this sets the root folder to the VS project directory
// so that any template updates in VS will be picked up
return new MyPathProvider();
}
}
protected override NancyInternalConfiguration InternalConfiguration
{
get
{
return NancyInternalConfiguration.WithOverrides(
x =>
{ x.ViewCache = typeof(MyViewCache); });
}
}
#endif
The new ViewCache just reloads the template on every request:
public class MyViewCache : IViewCache
{
...
public TCompiledView GetOrAdd<TCompiledView>(
ViewLocationResult viewLocationResult, Func<ViewLocationResult, TCompiledView> valueFactory)
{
//if (viewLocationResult.IsStale())
// {
object old;
this.cache.TryRemove(viewLocationResult, out old);
// }
return (TCompiledView)this.cache.GetOrAdd(viewLocationResult, x => valueFactory(x));
}
}
Somehow the viewLocationResult.IsStale() was always returning false.
By default, this is an instance of FileSystemViewLocationResult which just compares the last update time of the view, but the timestamp this.lastUpdated was being updated before calling IsStale() from the DefaultViewCache, so the template was never removed from the cache
public override bool IsStale()
{
return this.lastUpdated != this.fileSystem.GetLastModified(this.fileName);
}

Related

State is wiped out when page is refresh in blazor with fluxor

I am not sure how to handle this behavior, this is the Feature I have:
public class HolderFeature : Feature<HolderState>
{
public override string GetName() => "HolderState";
protected override HolderState GetInitialState() => new(holder: new ProductHolder(), persons: string.Empty);
}
And, everything works fine until a page is refreshed (pressing f5), the state is wiped out, I have this to handle the error:
protected override void OnInitialized()
{
if (HolderState.Value.QuotedProduct.Quotes != null)
{
//do the logic
}
else
{
//show error screen
PressedF5 = true;
}
}
What I expect is that even when the page is refreshed it shouldn't wipe out the state. how can I do that?
The state is stored in memory. When you refresh the page you are unloading it and starting from scratch, so all the memory is lost if it isn't persisted somewhere.

Can Caliburn.Micro be used for Visual Studio 2017 Extension Development?

I have been trying to use Caliburn.Micro in my extension that I am developing for Visual Studio 2017. I created my own custom bootstrapper. I used the example listed here Customer Bootstrapper. I kickstart my bootstrapper right after the extension's toolwindowpane is initialized. I have tried everything and it seems like I cannot get the Caliburn.Micro conventions to work. I am wondering if Caliburn.Micro can even work in an extension for Visual Studio!? The ToolWindowPane can host a WPF UserControl so I didn't think there would be an issue, but I cannot even get the ShellView to even see the ShellViewModel. Can someone let me know if Caliburn.Micro can work in this context???
Thanks!
Here is my BootStrapper:
public class ClassBootStrapper : BootstrapperBase<IShellViewModel>
{
private CompositionContainer container;
private static BootstrapperBase bootstrapper;
public static void Initialise()
{
if (null == bootstrapper)
{
bootstrapper = new ClassBootStrapper();
}
}
private ClassBootStrapper()
{
Initialize();
}
protected override IEnumerable<Assembly> SelectAssemblies()
{
var baseAssemblies = new List<Assembly>(base.SelectAssemblies());
var thisAssembly = Assembly.GetAssembly(typeof(ClassBootStrapper));
if (!baseAssemblies.Contains(thisAssembly))
{
baseAssemblies.Add(thisAssembly);
}
foreach (var assembly in baseAssemblies.ToList().Where(newAssembly => AssemblySource.Instance.Contains(newAssembly)))
{
baseAssemblies.Remove(assembly);
}
return baseAssemblies;
}
}
I test it in my side, it doesn't support the VS2017, you'd better to post the "Q & A" here:
https://marketplace.visualstudio.com/items?itemName=TheWinDev.CaliburnMicroWindows10Template#overview
So the extension team could provide much more helpful information for this extension.

Installer Custom action not working

I am trying to remove some additional files under the user profile Local Application Data folder after the uninstall of the app.
i read about custom action, so i wrote this
namespace RemoveUserAppDataCA
{
[RunInstaller(true)]
public partial class Installer1 : System.Configuration.Install.Installer
{
public Installer1()
{
InitializeComponent();
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
// Very important! Removes all those nasty temp files.
DeleteUserDataProfile();
base.Dispose();
}
void DeleteUserDataProfile()
{
try
{
string path = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..\\MyCompanyFolder"));
if (Directory.Exists(path))
{
Directory.Delete(path,true);
}
}
catch (Exception)
{
throw;
}
}
}
}
I added the dll file to the project setup , then a added a custom actions , then under the uninstall , i added the ddl file of the RemoveUserAppDataCA . i built the system.
i did the installation , but when i uninstall the app the app folderthe user profile Local Application Data remains (does not get deleted).
What is wrong about the work ??
I found the problem , the folder path was wrong. The system was pointing at
"C:\Users\UserName\AppData\App_Folder" instead of "C:\Users\UserName\AppData\Local\App_Folder"

ASP.NET MVC Debug-mode settings

Is there a way to setup some default settings for webpages being ran on debug mode?
For example, I'd like to set a default session userid on debug mode, but trying this in Application_Start() causes errors:
protected void Application_Start()
{
#if DEBUG
Session["User"] = "1"
#endif
}
I could instead choose to place that in controllers, but that'd require a lot of code duplication.
The reason that this throws an error is because the Session object is associated with a request. There is no request in the Application_Start event. You could move this logic to the Application_AcquireRequestState event handler and it would work fine.
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.IsDebuggingEnabled)
{
HttpContext.Current.Session["user"] = "1";
}
else
{
HttpContext.Current.Session["user"] = "0";
}
}
EDIT
After further research, I was mistaken. In the .NET pipeline, the above event handler is the first place that you can access the session object. It has not been retrieved from the server in the Application_BeginRequest which is why you are getting a NullReferenceException still. I tested the above code in MVC 5 and had no issues.
Also, instead of having to rely on compiler constants, you can easily tell if you are in debug mode or not using the above syntax of HttpContext.Current.IsDebuggingEnabled. This basically is a wrapper for checking the web.config attribute on the compilation tag and seeing if debug="true"
Note - You have to use the fully qualified name of HttpContext.Current.Session (as above) since the global event handlers do not have a direct inheritance of the current HttpContext.
You could use the Conditional attribute and put it on a method in your base controller. Something like this:
public class BaseController : Controller {
public BaseController() {
SetupDebugData();
}
[Conditional("DEBUG")]
public void SetupDebugData() {
Session["User"] = "1";
}
}
The call to SetupDebugData will be optimized away for Release builds. Then you just inherit from this controller in your other controllers:
public class AdminController : BaseController {
// ...
}
Yes, off-course.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
#if(DEBUG)
Console.WriteLine("This is debug mode");
#else
Console.WriteLine("This is release mode");
#endif
base.OnActionExecuting(filterContext);
}
This code will be work in MVC ( I use it since MVC3). Remember that you need to set release build and debug false in web.config when you deploy your asp.net app on server.

WinRT 8.1 settings in Caliburn.Micro

I'm trying to open a settings view in a Caliburn.Micro WinRT 8.1 app using VS2013 RC, but I keep getting an unhandled exception when opening it with the following message:
Value cannot be null. Parameter name: Could not parse the VisualElements from the app manifest.
I can reproduce the issues with the following steps:
create a new Windows Store app from VS2013 RC using the Blank app template.
add Caliburn.Micro via NuGet.
in App.xaml, change the base class to caliburn:CaliburnApplication (the namespace is declared as xmlns:caliburn="using:Caliburn.Micro").
in App.xaml.cs, change the class like this (for the CM-based settings I follow http://compiledexperience.com/blog/posts/settings-caliburn)
Code below:
public sealed partial class App
{
private WinRTContainer _container;
public App()
{
InitializeComponent();
}
protected override void Configure()
{
_container = new WinRTContainer();
_container.RegisterWinRTServices();
_container.PerRequest<MainViewModel>();
_container.PerRequest<SettingsViewModel>();
ISettingsService settings = _container.RegisterSettingsService();
settings.RegisterCommand<SettingsViewModel>("Test settings");
}
protected override object GetInstance(Type service, string key)
{
var instance = _container.GetInstance(service, key);
if (instance != null) return instance;
throw new Exception("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
protected override void PrepareViewFirst(Frame rootFrame)
{
_container.RegisterNavigationService(rootFrame);
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
DisplayRootView<MainView>();
}
}
Finally, create folders for Views and ViewModels in the solution add add to them the required items: MainViewModel, SettingsViewModel, MainView, SettingsView. The views just include a TextBlock with some text. MainViewModel derives from Screen, while SettingsViewModel derives from PropertyChangedBase. There is no relevant code in any of them.
When launching the app, I can see the main view; then I open the charms bar and click settings, and I find the label leading to my app settings; when I click it, I get the exception quoted above. Any hint?
You can find a full repro solution here: http://sdrv.ms/18GIMvB .
If you aren't ready to move to the alpha version of CM, you can update Callisto to 1.4.0 via NuGet. That fixed the error for me.
It seems that the new CM release (alpha 2) fixed the issue, so I'm adding some more information here to help other newcomers like me. Here is what I'm doing now:
In app's Configure I have some bootstrap code like:
...
ResourceLoader loader = ResourceLoader.GetForViewIndependentUse("Resources");
ISettingsService settings = _container.RegisterSettingsService();
settings.RegisterFlyoutCommand<ContentSettingsViewModel>(loader.GetString("SettingsContent"));
The ContentSettingsViewModel is a viewmodel for filtering some contents. The string got from resources is the label which will appear in the settings flyout (be sure there is an entry for this string, as passing an empty or null string triggers an exception). This VM is derived from CM Screen as I'm overriding OnActivate and OnDeactivate to load and save settings when the user opens or dismisses the settings page.

Categories

Resources