IIS Application Initialization with IIS 10.0 and WebAPI - c#

Hello and good morning everyone,
I ran into an issue where the services once started, are no longer subscribing to the service discovery. In testing they were running under IIS Express. However once I flipped it over to IIS and verified everything was still working; the service no longer hits the Application_Start() within the Global.asax.cs.
Doing a bit of research, it appears that IIS requires a little configuration to get this to do some initialization work once the Application Pool is started. I am running this in a Windows 10 Professional environment with IIS 10.0.17763.1
The goal: Get the service starting up to subscribe to the service discovery was it was running under IIS Express.
I first found on the MSDN the documentation for setting all of this up including prerequisites here IIS 8.0 Application Initialization
After going through all the steps and updating the required config entries, it appears I am still not Initializing my web service when the Application Pool starts.
I have created a new endpoint on the controller for testing purposes to get this to work.
AccountController:
[System.Web.Http.HttpGet]
public IHttpActionResult Init()
{
// here is where I am registering the service thats coming up
}
Route Definition file:
{"Name": "Account - Init",
"RouteTemplate": "api/{controller}/init",
"Defaults": "controller = AccountController, action = Init"}
Web.config
<applicationInitialization skipManagedModules="false" doAppInitAfterRestart="true" remapManagedRequestsTo="/api/account/init">
<add initializationPage="/api/account/init" />
</applicationInitialization>
I am under the assumption that the Initialization will only happen ONCE, and that happens when the Application Pool first starts, or is recycled. IIS internally will make a 'managed' call to the Web Application against the mapped resource it finds in the application's web.config file. Is my understanding of how it should be working incorrect? If so, could someone please clarify why?
I am not simply trying to 'get this to work'. I would like to understand why its 'not' currently working for me.
Thanks to all in advanced who take the time to respond here.

that is correct, your web.config will only be read once when the application starts.
you can add some logging messages to see it happen.
You can actually hit debugger points if you manage to connect your Visual studio to the application pool of the IIS process in time. There is an option to attach the debugger to a process, so you can use that.
This is painfully obvious in systems where the AppSettings are in a separate file, not web.config. if you make a change, nothing will happen, until you touch web.config which triggers an application restart.

Following up,
I fixed my own problem. It appears the code IS working correctly, that its hitting the Global.asax.cs Application_Start as it should. I had an exception being thrown not related to IIS after a change I made which was resulting in what appeared to "not work".
Following the instructions on the MSDN does work.

Related

Sudden IIS application's shutdown

I have a multiple versions of an ASP.net website, all of them are working fine except the latest version which recently started to stop suddenly. Each version runs in a different application pool. Our investigations resulted in the following:
Application_End event is getting fired after couple minutes from starting the web application. However, the Application_Start is not being triggered after that.
After the application is stopped, most pages works with no styles, as our styles are bundled using "BundleTable". All bundles return 404 error, but the login process which relies on a web service works fine, and moves me to the home page (with no styles due to 404 response)
Requesting any physical resource (image/js/css/svc) works fine
After the Application_End event get fired, the w3wp process related to this application's pool remains running. Killing it with task manager makes no change. it will start again without causing the application_start to get fired
Stop/restart/recycle IIS/pool doesn't cause the Application_Start to get fired (I'm checking using custom logging). Deleting asp temp files sometimes works but not everytime. Now I've tried everything but couldn't make it start again!
List item
I'm using windows server 2012 64x, with IIS 8.5 and .net V4.5. Any hints are appreciated
Update-1:
Here is a snapshot for the page with errors.
Update-2:
After making few tests and adding more logs here and there, I can summarize the issue in a simpler way:
First the issue shows only and only in the case I enable the "precompile during publishing" option while publishing my website, and merging all output DLLs in single assembly.
After publishing with the above configuration, the Application_Start event will triggered on first page request, which is normal, and the main code I have in this event is to register all CSS & JS bundles, and configure URL routing. The application will work fine for approx. 30 minutes, then the Application_End will be triggered (with "HostingEnvironment initiated shutdown" shutdown reason) but the Application_Start won't be triggered again!. The Strange thing that the application will continue to serve subsequent requests (Ex: connect to database, do logging, authenticate users, serving WCF services requests...) but all bundles and URL routings that are registered in the Application_Start are lost. Another hint that general errors (Ex: 404) which are processed in the global.asax file are not getting processed after the Application_End is triggered! It seems like the application just ignore or forget to process this file again!
The issue is finally solved after fixing all compilation warnings. I can't tell which one has fixed the issue, but thought to share my experience anyways. The warnings found was as for the below:
Removing unused variables (about 10) (shouldn't affect)
Duplicated namespace importing (about 10) (shouldn't affect)
We had an outdated WCF service proxy. So we generated the new one (couple new methods were not added, and some changes on data types. However, this service is usually being called by some external extension that was out of our testing scope
A warning related to a conflict in culture settings (AssemplyInfo.cs-> AssemblyCulture) between referenced projects (also not sure if this could affect, as when doing normal publish without merging pages & controls assemblies we don't have any issue)
Regards,

Cannot keep alive Web Application on IIS after Recycling or Restarting

I have an MVC application that send an e-mail periodically using Quartz.NET. Although the published application works properly on IIS, it cannot works after recycling application pool or restarting the application on IIS. Searching on the web I found several post suggesting to make some changes on config files or IIS, but none of them working properly. So, is there any method to solve the problem? I need a solution that can be applied on application side (or on IIS side if it is simple just making a config changes, etc.). I think this is a common problem when keeping an application on IIS, isn't it?
Note: I use Windows Server 2008 and IIS 7.5.
You do not mention in your question where your application is going to run so I guess it's going to be hosted in-house.
Following your comment I gather you do not have any problems installing and running a Windows Service on your server.
My suggestion - and something I've implemented in the past - is to use the ASP.NET MVC application only as a UI where you create, delete or suspend your jobs/triggers which will be persisted in a database so, whatever happens to your application, you won't lose your jobs/triggers and they will be executed as soon as the application goes back on-line.
The database will be shared with the other layer, the Windows Service, which will be responsible for running your scheduled jobs.
First step is to setup and use AdoJobStore to store Quartz.Net data. As you can see in the post there are a few providers you can use.
Second step is to create and configure your Windows Service. I would use TopShelf to host it. The implementation is very simple and straightforward; plus you can use the Quartz.Net integration provided here.
If you go through the documentation you won't find any problem integrating the solution.
Quartz.Net depends on some configuration you have to add in your app.config/web.config. In this answer there's a detail explanation about the configuration and AdoJobStore.
There are a few things to remember implementing this type of solution.
Your Web Application is going to set the property threadPool to ZeroSizeThreadPool in your config:
<add key="quartz.threadPool.type" value="Quartz.Simpl.ZeroSizeThreadPool, Quartz" />
or in your code:
properties["quartz.threadPool.type"] = "Quartz.Simpl.ZeroSizeThreadPool, Quartz";
and it's never going to start the Scheduler (your windows service is going to use that).

IIS stops responding after recompile

I have my web app I'm developing under local IIS (so not not the visual studio embedded one). It works fine, I can go from page to page...
But if I then change the code and recompile, IIS stops responding properly for ~2 minutes. If I attach the debugger, then there's no executing code, but it just won't serve any pages.
If I stop the App Pool in IIS, then I get a 503 error instantly, but I then am prevented from restarting the App Pool for ~2 minutes with error: Cannot Start Application Pool / There was an error while performing this operation. / Details: / The service cannot accept control messages at this time. (Exception from HRESULT: 0x80070425)
As you can imagine, this is crippling my productivity. Only started happening a couple of days ago, I haven't made any changes to the code which I would have though would cause this problem... and it doesn't matter which page I touch and recompile anyway, it takes just as long to recover. Nothing in the event log.
Any clues as to where to start looking?
Add the following line to your web.config:
<compilation optimizeCompilations="true" />
related article: http://www.dnnsoftware.com/community-blog/cid/135019/a-small-webconfig-setting-that-can-save-you-development-time
I had a similar problem and the installation of the following hotfix fixed the problem for me:
https://support.microsoft.com/en-uk/kb/3090034

Displaying a stub page while ASP.NET app starts

Can I display a specific page while ASP.NET application is still in the process of initialization?
We've got a huge ASP.NET application that takes about 30 seconds to complete its Application_Start() handler after each redeploy or AppDomain restart. Showing a nice self-reloading "temporarily unavailable" page during that time will greatly improve the experience for first users.
I tried to extract the initializer code into a different thread, but it has a lot of dependencies: the HttpContext, Server and several other classes are unavailable from derived threads. The code becomes intervowen and incomprehendable, so I'm looking for a better solution. Maybe some IIS configuration or extension?
Well, since IIS 7.5 you can use Application Initialization for that (http://www.iis.net/downloads/microsoft/application-initialization) that will make it possible to either show a "splash-Screen" or to just pre-start Application-Pools.
Here is the explanation for IIS8: http://www.iis.net/learn/get-started/whats-new-in-iis-8/iis-80-application-initialization It will work similar with IIS7.5, but there you have to install the module beforehand.
And here a link taken from the comments: http://blogs.msdn.com/b/abhisk/archive/2013/08/16/configuring-application-initialization.aspx
You could load a static html page or page that is not effected by the system startup, then via ajax poll/check something (value, etc) that will only be available once the application starts, this way you could have an animation or some loading information on the page.
I think you're looking for something that is impossible. So you want to create an Application_Start that takes a long time to finish, and you want your application to be responsive during that time. Application_Start is a synchronous event, meaning that not a single request will begin processing before it completes. It is its job after all.
You have to loosen up your requirements somehow. Here are some ideas.
A new HTTP layer
As I said, you cannot run .NET code in your application before Application_Start finishes. But you can run another, different application.
So let's create another application that faces the clients. A reverse proxy or similar. I'm sure there are reverse proxy implementations out there which allow you to do some scripting and solve the issue. On the other hand, I have myself written a simple reverse proxy in C#. When it received an HTTP request, it created an HttpWebRequest and relayed it to another URL. It supported GET and POST, it is working in production for years now. If you are interested, I may be able to share some details about it.
The only thing you have to solve is how your backend application communicates with the frontend. That's easy, you can use WCF, IPC, create a simple 0-byte marker file somewhere, anything at all. When your Application_Start starts, you can create that 0-byte file, and when it completes, you delete it.
Note that many things happen after you shut down your application, restart it, and before the Application_Start runs. IIS initialization can take a few seconds. So instead of the 0-byte marker file, which only has 2 states (exists/not exists), you can expose a simple WCF service, with named pipes for example. It can have 3 states: doesn't respond at all (the application is stopped), it responds that the application is starting up, or it responds that the application is running. This WCF service has to be self-hosted and run in the background, because IIS won't respond obviously.
HTML/JS magic
It is basically the same idea as above. It is easier because you don't have to set up another application, but less flexible. You have to create an HTML landing page for your application and you have to make sure that users don't bookmark any other page. If you can do that, you are in luck. You can use the ideas from the above solution about how your application can communicate with the outside world while it's starting up. You can not use simple web services hosted in IIS, but you can host your own WCF services without any problems (create your own ServiceHost, etc.). Of course, this self-hosted WCF service won't run at the same host:port as your application. But it's pretty easy to expose a JSON service in WCF.
So, in your HTML landing page, you write some JS AJAX code that queries your self-hosted JSON service. If there is no response, you can tell the user that the application is not running at all. If the service says that it is starting up, you can tell that to the user. If the service says that the application is running, then you redirect your user.
This will not work if your users are browsing your site already when you shut it down. See, that's why you need an entirely new layer.
IIS magic
This is a somewhat uncharted territory for me. In integrated mode, .NET is an integral part of IIS, so I think it's hard to work around it. In classic mode, however, .NET is run as an ISAPI extension. So you can, in theory, write a new ISAPI extension that runs before .NET. The bad news is that it has to be written in C/C++. But it is obvious, because like I said, you cannot run .NET code before Application_Start finishes. But IIS is not dead during that time, so solve it at the IIS level. This can get ugly and I'm only 99% sure that it is actually possible.
Refactoring
The above are all workarounds. You really should refactor your code so that Application_Start finishes quickly. It is not meant to be a heavyweight function. There is already a framework for preloading ASP.NET apps. If you tell us why you need HttpContext and Server in your initialization code, we are here to help you with those problems.

Strange Problem with a .NET Windows Service

I have two Windows services written in C# following the same patterns and methodology.
Both services were development tested against a Windows 7 VM and QA tested on Windows Server 2008 VM. Both services have been installed and uninstalled many times under these test environments without issue, however upon installing in the production environment (Windows Server 2008) one of the two services refuses to start.
To install the services we are using InstallUtil.exe with ServiceInstaller and ServiceProcessInstaller components attached to the service.
By all appearances, the failing service installs successfully. InstallUtil.exe reports success and the service appears in the Services snapin. You can also locate the service in the registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Blah Blah. However, if you attempt to start the service you get the following:
net start blah.blah.exe
"The service name is invalid."
...or going through the Services snapin...
"Windows could not start the "Blah Blah" service on Local Computer. Error 1053: The service did not respond to the start or control request in a timely fashion."
I have added some event logging to the constructor of the service class failing service, but it does not appear to get called.
As this is a production box, there is no Visual Studio on the box and remote debugging is out of the question.
Is there any other way for me to gain debugging info on why the failing service isn't starting?
Is there any other obvious-ish reason that I might see this kind of issue?
Edit: I should have also mentioned.. The only other evidence of a problem in the Windows Event Viewer is two messages in the System log from the Service Control Manager:
"A timeout was reached (30000 milliseconds) while waiting for the Blah Blah service to connect.
"The Blah Blah service failed to start due to the following error:
The service did not respond to the start or control request in a timely fashion."
Edit: Resolved
The issue ended up being a combination of a configuration mistake and a bug that was hiding it. See my answer below for more details.
Jeopardy Answer: "How might invalid custom configuration combined with a bad global exception handler manifest itself in a .NET Windows service?"
Figured it out.
The root cause of the problem was an invalid custom configuration section in the app.config. We use a custom configuration section to configure the service from the app.config and the assembly and namespace of the ConfigurationSection derived class had changed recently.
As it turns out, our production configuration was looking for the definition of the custom ConfigurationSection in the wrong assembly and the exception thrown when failing to instantiate it was getting hidden by a bug where exceptions caught early in the life of the service would attempt to be logged to the custom log rather than the Application event log. (Since the event log source did not exist on the custom event log, this would throw another exception from the global exception handler and the service would die in the constructor.)
This second exception did not get logged anywhere and we only found it through code inspection.
The resolution was to fix the configuration and to modify the global exception handler to only attempt to write to the Application event log using the service name as the event log source. (InstallUtil registers the service name as an event log source on the Application log.)
Thanks for the help everyone! Sorry this particular issue ended up being so specific to our setup.
It could be possible from the error message that you've described
net start blah.blah.exe "The service name is invalid."
That the name that you gave the service in the service install component that you added in visual studio is not what you think it is.
I've had this problem quite a few times with developers misnaming services in installs.
what are you trying to do on service start?
also check the account through which the service is running and the account has the necessary privileges.
I've run into problems like this many times while programming my own services, so I'll just list out a bunch of things that at various points solved my problems and hope that they help you:
I've had to restart services.msc because I've uninstalled a service it still thought it had a reference to. However, when I would start it, the "service was invalid"
If you're making the service from a console application (so that it can be debugged) but forget to change it back to a service, it won't start.
When I was using InstallUtil.exe, sometimes it would attempt to install multiple copies, so I switched to just using a Setup Project.
Hope that helps in some way.
This is a common issue. What code do you have in your Start event?
You should only have code that activates a Timer when the service starts. This allows the Start event to complete quickly and notify the controller. If the execution takes longer than that, you will get the error you received. There might be some reason (possibly data-related) why its taking longer in production.
When the Timer ticks, execute your code and stop the Timer. Obviously, also put everything in try/catch and log the exceptions.
It is possible for this error to occur when
your service is depending on another service/application
or due to invalid app.config configurations
Encountered the same issue when Entity Framework was unable to connect to the database server due to lack of permission.
Better to add a global level error logging mechanism to your application to debug the issue easily.Event Viewer might not reveal exact details in some scenarios.

Categories