How do i update live content on Nancy Hosting Framework - c#

Iam using Nancy Framework with C# and my views are rendered from HTML files. If i need to udate the code in my HTML,CSS or JS (which is part of the content), I have to go through the long annoying process of
Stopping the running C# project
Editing my HTML,CSS or JS File
Saving the changes
Running the C# project
Refreshing the browser
Waiting for the connection to localhost:8080 to be established (This usually takes a bit longer on the first run and that is even more annoying)
7.Finally i get to see if that CSS styling has been applied...if it has not be applied, i have to start the whole process from 1.
Please help me if u have a better way of doing this if not maybe just explain to me why i always have to wait a few more seconds for the first run of the C# project to start allowing connections on the browser.

Nancy does not cache CSS or JS files, they are pass-through files when they exist under Content folder, or if you explicitly set them up in the static conventions.
To disable View Caching, simply disable caches in your bootstrapper:
StaticConfiguration.DisableCaches = true
Edit:
Based on your comment:
https://github.com/richorama/Jukebox/blob/master/Jukebox/Controllers/Home.cs#L11
namespace Jukebox.Controllers
{
public class Home : NancyModule
{
public Home()
{
Get["/"] = x =>
{
return Response.AsFile("default.htm");
};
}
}
}
This will load the htm file off the disk every request. So I'm not entirely sure what issues you're running into. None-the-less try disabling the caches.
Also caching is only enabled when you're running the code in Release mode...
Edit 2:
Since you're using a console app and files are copied to the bin.
https://github.com/NancyFx/Nancy/wiki/The-root-path#changing-the-root-path
Create a implementation of the rootpath provider pointing to your dev directory. Configure it to only run during development.

Do you get 304 - Not Modified HTTP status code for the HTML, JS and CSS files? If so, then the files are cached by browser. Disable the caching either on the server side as Phill suggested or disable the browser caching (which might be counter-productive).

Related

VS2013 publish Web deployment task failed The file is in use

I am using VS2013 Premium to publish a site to Windows Server 2012.
All files publish ok except these:
SqlServerTypes\x64\msvcr100.dll
SqlServerTypes\x64\SqlServerSpatial110.dll
SqlServerTypes\x86\msvcr100.dll
SqlServerTypes\x86\SqlServerSpatial110.dll
I get this kind of errors for each of the above files I tried to publish:
Web deployment task failed. (The file 'msvcr100.dll' is in use. Learn more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_FILE_IN_USE.)
Interrestingly, these files were published the first time (when they were not on the server), then they are no longer overwritten. Tried with 2 different web servers.
I have followed the guide here:
http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
...But it only managed to put the site offline (VS is placing the app_offline.htm) but publish still fails with the same error.
All other files publish perfectly.
Any ideas?
You can take you app offline during publishing which hopefully should free up the lock on the file and allow you to update it.
I blogged about this a while back. The support outlined was shipped inside of the Azure SDK and Visual Studio Update. I don't remember the exact releases but I can find out if needed. Any update dating around/after that blog post should be fine.
Prerequisites:
VS 2012 + VS update / VS 2013 + VS Update / VS2015
MSDeploy v3
Note: if you are publishing from a CI server the CI server will need the updates above as well
Edit the publish profile
In VS when create a Web Publish profile the settings from the dialog are stored in Properties\PublishProfiles\ as files that end with .pubxml. Note: there is also a .pubxml.user file, that file should not be modified
To take your app offline in the .pubxml file add the following property.
<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
Notes
ASP.NET Required
The way that this has been implemented on the MSDeploy side is that an app_offline.htm file is dropped in the root of the website/app. From there the asp.net runtime will detect that and take your app offline. Because of this if your website/app doesn't have asp.net enabled this function will not work.
Cases where it may not work
The implementation of this makes it such that the app may not strictly be offline before publish starts. First the app_offline.htm file is dropped, then MSDeploy will start publishing the files. It doesn't wait for ASP.NET to detect the file and actually take it offline. Because of this you may run into cases where you still run into the file lock. By default VS enables retrys so usually the app will go offline during one of the retrys and all is good. In some cases it may take longer for ASP.NET to respond. That is a bit more tricky.
In the case that you add <EnableMSDeployAppOffline>true</EnableMSDeployAppOffline> and your app is not getting taken offline soon enough then I suggest that you take the app offline before the publish begins. There are several ways to do this remotely, but that depends on your setup. If you only have MSDeploy access you can try the following sequence:
Use msdeploy.exe to take your site offline by dropping app_offline.htm
Use msdeploy.exe to publish your app (_make sure the sync doesn't delete the app_offline.htm file_)
Wait some amount of time
Publish the site
Use msdeploy.exe to bring the app online by deleting app_offline.htm
I have blogged how you can do this at http://sedodream.com/2012/01/08/howtotakeyourwebappofflineduringpublishing.aspx. The only thing that is missing from that blog post is the delay to wait for the site to actually be taken offline. You can also create a script that just calls msdeploy.exe directly instead of integrating it into the project build/publish process.
I have found the reason why the solution at
http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
did not work for the original poster, and I have a workaround.
The issue with the EnableMSDeployAppOffline approach is that it only recycles the app domain hosting the application. It does not recycle the app pool worker process (w3wp.exe) which the app domain lives in.
Tearing down and recreating the app domain will not affect the Sql Server Spatial dlls in question. Those dlls are unmanaged code which are manually loaded via interop LoadLibray calls. Therefore the dlls live outside the purview of the app domain.
In order to release the files locks, which the app pool process puts on them, you need to either recycle the app pool, or unload the dlls from memory manually.
The Microsoft.SqlServer.Types nuget package ships a class which is used to load the Spatial dlls called SqlServerTypes.Utilities. You can modify the LoadNativeAssemblies method to unload the unmanaged dlls when the app domain is unloaded. With this modification when msdeploy copys the app_offline.htm the app domain will unload and then unload the managed dlls as well.
[DllImport("kernel32.dll", SetLastError = true)]
internal extern static bool FreeLibrary(IntPtr hModule);
private static IntPtr _msvcrPtr = IntPtr.Zero;
private static IntPtr _spatialPtr = IntPtr.Zero;
public static void LoadNativeAssemblies(string rootApplicationPath)
{
if (_msvcrPtr != IntPtr.Zero || _spatialPtr != IntPtr.Zero)
throw new Exception("LoadNativeAssemblies already called.");
var nativeBinaryPath = IntPtr.Size > 4
? Path.Combine(rootApplicationPath, #"SqlServerTypes\x64\")
: Path.Combine(rootApplicationPath, #"SqlServerTypes\x86\");
_msvcrPtr = LoadNativeAssembly(nativeBinaryPath, "msvcr100.dll");
_spatialPtr = LoadNativeAssembly(nativeBinaryPath, "SqlServerSpatial110.dll");
AppDomain.CurrentDomain.DomainUnload += (sender, e) =>
{
if (_msvcrPtr != IntPtr.Zero)
{
FreeLibrary(_msvcrPtr);
_msvcrPtr = IntPtr.Zero;
}
if (_spatialPtr != IntPtr.Zero)
{
FreeLibrary(_spatialPtr);
_spatialPtr = IntPtr.Zero;
}
};
}
There is one caveat with this approach. It assumes your application is the only one running in the worker process that is using the Spatial dlls. Since app pools can host multiple applications the file locks will not be released if another application has also loaded them. This will prevent your deploy from working with the same file locked error.
There are known issues with IIS and file-locks (why they aren't solved yet i dont know).
The question i want to ask however is if you even need to re-deploy these files?
I recognize the file-names and recall them to be system-files which should either already be present on the server or simply not need to be re-deployed.
I am not very experienced when it comes to IIS but i have ran into this problem before and several of my more experienced co-workers have told me that this is as i said a known IIS-issue and i believe the answer to your question is:
Avoid deploying unnecessary files.
try again
Reset website
try again
iisreset
I think what would be the easiest thing to do is to make these dll's as CopyLocal as true. I am assuming these dll's are pulled out from program files folder. Try marking them as copylocal true and do a deployment.Try to stop any IIS local process running in your local machine.
Watch out you don't have one of those new-fangled cloud backup services running that is taking file locks - and also you don't have things open in explorer or a DLL inspection tool.
I think it's kind of ridiculous that MS doesn't make better provisions for this problem. I find that 9 times out of 10 my deployment works just fine, but then as our traffic increases that can become 1 in 10 times.
I am going to solve the problem with :
two applications MySite.A and MySite.B, where only one is running at a time.
I always then deploy to the dormant site.
If there's a problem during the deployment it will never cause the whole site to go down.
If there's a major problem after deployment you can revert back very easily.
Not quite sure how I'm implementing it, but I think this is what I need to do.

Application_start not working

I have written some code in the application_start() method in my global.asax file. It does not get called when I deploy my application on IIS server. The code is accessible when I run it in the .NET framework.
I've tried to restart the application many times, but it's still not working.
I've also tried the suggestion from the following link.
Application_Start not firing?
There are few things you need to know before you are trying to debug Appplication_Start. There are -
One : When the code executes and why it is almost impossible to debug by attaching to it.
The application start method is executed when the application pool starts and your website is being started up for the first time. If you deploy new deliverables to IIS, then IIS might restart it itself, but there is no guarantee that it will. So, deploying new codes does not guarantee that it will restart the pool and he execution of application start. You should restart your application pool to guarantee execution of application start.
While debugging IIS applications, Visual Studio attaches itself to a process something named w3wp.exe or similart (I forgot the actual executable name), which is the worker process and only available after, remember after, your application pool is up and your site is up. So, in other words, if you are seeing this in service list, then the application start has already been executed and attaching to it will not give you a chance to debug it. It is kind of a tug of war with time.
So, in other words, it is kind of impossible to debug application start unless you are very very quick.
Two, the solution 1 - With Dev Server
Launch your application in visual studio with Asp.net development server or IIS express, then you will be able to debug. But if you really want to debug on IIS, then check the next section
Two, the solution 2 - With IIS
There is a library in the name System.Diagnostics, Debuggerand it has a nice way to call debugger in code. You can read it here - http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break(v=vs.110).aspx
Modify you application start with this -
public void Application_Start(){
....... //other codes
Debugger.Break() or Debugger.Launch()
}
When this line executes, IIS will halt execution, and will show you a debugger selector window (similar to the one attached), keep your solution open in vs and select that vs from the list, will be able to debug as usual... :)
In case you are using windows 8 and the debugger does not launch, read this article to enable it -
http://blogs.msdn.com/b/mapo/archive/2013/11/07/debugger-launch-not-displaying-jit-debugger-selection-popup-on-windows-8-8-1.aspx
Three: A very important thing
I noticed that you said, you are adding db entries in Application_Start. You should keep in mind that, Application_Start does not have a HttpContext, ViewContext, So your db access code may fail for so many others reasons.
Make sure that the Global.asax file is actually deployed to the destination folder in the root. If the file is not present then the code behind you have written for Application_Start will never be called.
Also make sure the signature is correct
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {/*do something here like logging so you know it was called*/}
}
If you are running Server 2008R2 (or earlier) and/or IIS 7.5, you might want to look into the Application Initialization module. This can be downloaded here:
www.iis.net/downloads/microsoft/application-initialization
With IIS versions prior to 8.0, the application start is not called until the first web request arrives. I'm reading your question as you want your application start to be fired before the first web request, yes?
Here is a fantastic guide to configuring this module (if it applies to you):
https://blogs.msdn.microsoft.com/benjaminperkins/2014/01/07/configure-the-iis-application-initialization-module/
The key takeaways is that you need to set your app pool to 'AlwaysRunning' instead of 'OnDemand'. You also need to set a preloadEnabled flag for your website. Once both of these are done, fire off an iisreset and you should see the results of your application start (look in the database since it's writing there).
Other answers are relevant as well, in that this is tough to debug and you're missing all the niceties you're used to such as a httpcontext in app start.
If you are running IIS 8.0 - you should still read the above link to configure preloading.
This did work for me:
Menu -> Build -> Clean Solution
Menu -> Build -> Rebuild Solution
Then, Application_Start() was fired only for the first time.
In my case in production environment App_global.asax.compiled was missing and all content of global.asax not fired.

How to save clicking counter in c#

I build web-site and want to count clicks on some button. I create and try this class of counter:
public static class Counter
{
public static int counter = 0;
}
Every time I click on the button the counter is increament (counter++) ans I see it in my site, But, if I close the chrome and enter again to my site the counter starts from zero.
How can I save the counter? "Static" dont need to do that?
My bet is that it happens because the application space is flushed - it shouldn't reset just because you closed your browser window, thus abandoning the current session (if the session cookie isn't persistent, that is.)
Visual Studio may republish your files (if using a remote IIS) or just plainly restart a local IIS Express instance, depending on how you set your development environment; I do believe setting a specific content as Static would cause it to be available to all current sessions.
That said, you may want to keep it under the current session (using the Session object).
Optionally, if you want to persist information in between server restarts, you may try reading and writing to a local storage, such as a plaintext or XML file. You can find a very nice article about this on the following link:
http://www.codeproject.com/Articles/544839/Implement-ASP-NET-custom-XML-file-configuration
A more sophisticated version would use a local (or remote) database, for example.
Hope it works for you.
static fields are unique per-process. Depending on your application pool configuration, you could have 2, 20 or 100 copies of that.
They're also not thread safe. There are very, very few instances (pun) where a static member is appropriate.
Just off the top of my head, a particular "instance" of a static will disappear when:
The application pool is recycled. On IIS, this defaults to 20 minutes of inactivity.
The application process exits (you may have multiple processes running within your app pool). This happens as part of (1), but will also happen if, say, you're using the Visual Studio debug web server (Cassini), have your project configured to launch the site for debugging, and close the browser that was launched initially. (This happens because VS considers closing the browser that it launched equivalent to saying "I'm done playing. Back to coding now," or hitting the stop button.)
Another thread overwrites the value you've stored (google "race condition.")
You really, really should be storing this in a database. If you're building a website, you need a database anyway. ANYTHING related to application state should be stored in the database.
ALSO, this really, really shouldn't be happening server-side. Are you really performing a postback every time someone clicks anywhere on a page? If so, you have JavaScript in place to handle that, so just skip this insanity, have said script fire off an AJAX request, and have the target handler log it in the database.
Looks like your using a web site so presuming ASP.net. There are a number of ways to store the information. Database could be one or a persistent cookie could be the way to do it. See this article on how to create cookies: How do I set/unset cookie with jQuery?
You can try save it in session and then it will stay until the session is time out(20 minutes) if you want it to long time just write it to file in known location and when you close the web write the value to the file and when the web is up again take the vakue from the file.

How can I debug this web service?

I have a simple web service that looks something like this:
[WebMethod]
public OrderForecastItem GetOrderForecast(int shipTo, string catalogName, bool showPricing)
{
return OrderForecastManager.GetOrderForecast(shipTo, catalogName, showPricing);
}
I'm calling it from another place in a fairly simple way:
using (OrderForecastWS.OrderForecastWS service = new OurSite.Web.Reporting.OrderForecastWS.OrderForecastWS())
{
OrderForecastItem orderForecastItems = service.GetOrderForecast(2585432, "DENTAL", false);
}
After some gymnastics to get the systems to understand that I'm talking about the same type of objects on the client and server sides (I had to open the Reference.cs file inside my Web References, delete the generated OrderForecastItem and add a link to our real OrderForecastItem), the system runs and attempts to get the item.
Unfortunately, it now bombs during the service call, claiming:
Exception There is an error in XML document (1, 1113).(InvalidOperationException)
I can go to the web service in a browser, put in the same values, and I get a seemingly valid XML response. (It looks okay to me, and I ran it through the XML parser at W3Schools, and it cleared it.)
I think the numbers in the error are supposed to be the line and character number...but the browser seems to reformat the xml document, so I can't easily see what the original (1, 1113) location is.
I don't see an easy way to intercept the response and examine it, since it seems to be blowing up as soon as it gets it.
How can I debug this?
If you control the service, you can step into it. If it is a part of your solution and hosted in VS WebDev on your local box, just F11 from Visual Studio, if service is hosted remotely (eg by IIS on other computer) run remote debugging tool on service host msdn, and then you will be able to step in to the service remotely.
By the way, you can tell Visual Studio to re-use objects from referenced libraries for types from the service: just pick configure Service Reference from service context menu and tell which libraries to re-use.
On second thought this error may happen if returned XML could not be deserialized into your business object. May happen when class is changed on either side, or you are trying to use different version of business library than service is using.
If you use Firefox, I'd recommend Firebug. You'll be able to easily view the response from the website in its original format, which might get you closer to the line and position you're looking for.

How to update XBAP to latest version on client computer?

I developed a XAML browser application (XBAP) that is embedded within an ASP.NET web page. I am having a problem getting the latest version of the XBAP to update on the client computer. During development, I have had to use the Mage.exe tool to clear out the application cache so that my changes will be seen when running on my local computer. Besides executing Mage.exe -cc in the command line, I have also found rundll32 dfshim CleanOnlineAppCache to work just as well.
However, I do not want to ask customers to run any commands in the command line. What will I have to do to make the XBAP automatically update on the client computer? Instead of the updated XBAP refreshing on the client computer, the previous version of the XBAP continues to run.
Update
I created a bounty on this question because I have the same issue. From what I read online, XBAPs are supposed to compare the cached version # with the version # of the one on the webserver, and download the new version if it's different. I've verified that my version numbers are different, but the cached copy is still the one that is running when I launch the XBAP.
The cached copy also comes if I launch the XBAP outside of the asp.net page, although I do get the new version if I change the url parameters.
Update #2
I've discovered that the XBAP does automatically update on XP 32-bit machines, but not on my Windows 7 64-bit machine.
You could try something like this, although I use it in XAPs not XBAPs it might work for you too:
(snippet follows)
public partial class App : Application
{
/// <summary>
/// Creates a new <see cref="App"/> instance.
/// </summary>
public App()
{
Application.Current.CheckAndDownloadUpdateAsync();
// rest of code
EDIT
Was gonna suggest incrementing version number between publishes but it seems that's already been taken care of. Does this behavior happen on all browsers ? Might be some IE-specific bug/oddity (i've seen plenty of IE-only misbehaviors... wouldn't surprise me)
Years ago, we had this problem with an ordinary website. It kept haunting us, and in the end, we ended up changing the url prefix for each new version. The very first page was never cached, and forwarded to the updated url.
Its a workaround, I know, but a very reliable one.
You can use ClickOnce to deploy your application. If you want to force user to update just set minimum required version for the application (it's in Application Updates dialog box).
without the correct cache headers your browser may be preventing downloading the xbap.
clear cache to see if this fixes it.
alternatively use:
<%string versionInfo = typeof (AVSTX.POS.WebMvc.Controllers.HomeController).Assembly.GetName().Version.ToString(); %>
<param name="source" value="<%=ResolveUrl("~/ClientBin/AVSTX.POS.WebRia.xap?version=" + versionInfo) %>"/>
to create a new url which the browser cannot cache at this point.
It is based on inspecting the host assembly version so make sure to increment
[assembly: AssemblyVersion("3.4.9.0")]
[assembly: AssemblyFileVersion("3.4.9.0")]
this solution won't solve the dynamic modules you may download in the future. you will need to fix the actual cache headers if this is your problem.
edit 1: code to disable browser caching
//http://stackoverflow.com/questions/1160105/asp-net-mvc-disable-browser-cache
//http://developer.yahoo.com/performance/rules.html#expires
//http://ray.jez.net/prevent-client-side-caching-with-httpmodules/
//http://stackoverflow.com/questions/2281919/expiry-silverlight-xap-file-from-browser-cache-programmatically
public class XapFileHttpModule : IHttpModule
{
#region IHttpModule Members
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
public void Dispose()
{
}
private void context_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if(context.Request.FilePath.Contains(".xap"))
{
context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
context.Response.Cache.SetValidUntilExpires(false);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetNoStore();
}
}
#endregion
}
Application caching is done via manifest files caching, when manifests signatures changes, runtime will upgrade the local files (moreover it just upgrade the changed files). Just sure that you has the right headers sent on HTTP responses. Sometimes dynamic pages cache settings or hosting providers global settings interfere. For me, it always works out of the box.
ClickOnce worked for me like a charm. Also make sure that you're versioning your XBAP properly.
I deploy my Xbap by simply copying filest to ClientBin directory in my web project.
I display it in iframe.
To make application "refresh" version I have to change "Publish Version" in Xbap project before build.
Project Properties -> Publish -> Publish Version.
This changes version in xbap and manifest file forcing clients to download newest version.

Categories

Resources